Added short aliases make-buffer / buffer? / buffer-append! / buffer->string / buffer-length on both OCaml and JS hosts, sharing the existing StringBuffer value type. buffer-append! auto-coerces non-strings via inspect. Rewrote the OCaml host inspect function to walk a single shared Buffer.t instead of allocating O(n) intermediate strings via String.concat at every recursion level. inspect underlies sx-serialize and error-path formatting, so this benefits the tightest serialization paths. Median improvements (bin/bench_inspect.exe, best-of-3 of 9-run min): tree-d8 (75KB): 5.31ms -> 1.30ms (-76%) tree-d10 (679KB): 81.89ms -> 16.02ms (-80%) dict-1000: 0.80ms -> 0.31ms (-61%) list-2000: 0.74ms -> 0.33ms (-55%) Tests: OCaml 4545 -> 4550. JS 2591 -> 2596. Zero regressions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
165 lines
5.3 KiB
Plaintext
165 lines
5.3 KiB
Plaintext
(defsuite
|
|
"string-buffer"
|
|
(deftest
|
|
"make-string-buffer creates a string-buffer"
|
|
(let ((buf (make-string-buffer))) (assert (string-buffer? buf))))
|
|
(deftest
|
|
"string-buffer? is false for non-buffers"
|
|
(assert= false (string-buffer? "hello"))
|
|
(assert= false (string-buffer? 42))
|
|
(assert= false (string-buffer? nil))
|
|
(assert= false (string-buffer? (list)))
|
|
(assert= false (string-buffer? {:key "val"})))
|
|
(deftest
|
|
"type-of returns string-buffer"
|
|
(assert= "string-buffer" (type-of (make-string-buffer))))
|
|
(deftest
|
|
"empty buffer converts to empty string"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(assert= "" (string-buffer->string buf))))
|
|
(deftest
|
|
"empty buffer has length zero"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(assert= 0 (string-buffer-length buf))))
|
|
(deftest
|
|
"single append accumulates string"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "hello")
|
|
(assert= "hello" (string-buffer->string buf))))
|
|
(deftest
|
|
"multiple appends join in order"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "foo")
|
|
(string-buffer-append! buf "bar")
|
|
(string-buffer-append! buf "baz")
|
|
(assert= "foobarbaz" (string-buffer->string buf))))
|
|
(deftest
|
|
"length tracks total bytes appended"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "abc")
|
|
(string-buffer-append! buf "de")
|
|
(assert= 5 (string-buffer-length buf))))
|
|
(deftest
|
|
"append returns nil"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(assert= nil (string-buffer-append! buf "x"))))
|
|
(deftest
|
|
"appending empty string is harmless"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "start")
|
|
(string-buffer-append! buf "")
|
|
(string-buffer-append! buf "end")
|
|
(assert= "startend" (string-buffer->string buf))
|
|
(assert= 8 (string-buffer-length buf))))
|
|
(deftest
|
|
"buffer is still usable after string-buffer->string"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "hello")
|
|
(string-buffer->string buf)
|
|
(string-buffer-append! buf " world")
|
|
(assert= "hello world" (string-buffer->string buf))))
|
|
(deftest
|
|
"two buffers are independent"
|
|
(let
|
|
((b1 (make-string-buffer)) (b2 (make-string-buffer)))
|
|
(string-buffer-append! b1 "one")
|
|
(string-buffer-append! b2 "two")
|
|
(string-buffer-append! b1 "ONE")
|
|
(assert= "oneONE" (string-buffer->string b1))
|
|
(assert= "two" (string-buffer->string b2))))
|
|
(deftest
|
|
"loop building — linear string concat"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(let
|
|
loop
|
|
((i 0))
|
|
(when
|
|
(< i 5)
|
|
(string-buffer-append! buf (str i))
|
|
(loop (+ i 1))))
|
|
(assert= "01234" (string-buffer->string buf))
|
|
(assert= 5 (string-buffer-length buf))))
|
|
(deftest
|
|
"building CSV row with separator"
|
|
(let
|
|
((buf (make-string-buffer)) (items (list "a" "b" "c" "d")))
|
|
(let
|
|
loop
|
|
((remaining items) (is-first true))
|
|
(when
|
|
(not (empty? remaining))
|
|
(when (not is-first) (string-buffer-append! buf ","))
|
|
(string-buffer-append! buf (first remaining))
|
|
(loop (rest remaining) false)))
|
|
(assert= "a,b,c,d" (string-buffer->string buf))))
|
|
(deftest
|
|
"unicode characters accumulate correctly"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "こんにちは")
|
|
(string-buffer-append! buf " ")
|
|
(string-buffer-append! buf "世界")
|
|
(assert= "こんにちは 世界" (string-buffer->string buf))))
|
|
(deftest
|
|
"repeated to-string calls are consistent"
|
|
(let
|
|
((buf (make-string-buffer)))
|
|
(string-buffer-append! buf "test")
|
|
(assert= (string-buffer->string buf) (string-buffer->string buf))))
|
|
(deftest
|
|
"building with join pattern produces correct output"
|
|
(let
|
|
((buf (make-string-buffer))
|
|
(words (list "the" "quick" "brown" "fox")))
|
|
(let
|
|
loop
|
|
((remaining words) (sep ""))
|
|
(when
|
|
(not (empty? remaining))
|
|
(string-buffer-append! buf sep)
|
|
(string-buffer-append! buf (first remaining))
|
|
(loop (rest remaining) " ")))
|
|
(assert= "the quick brown fox" (string-buffer->string buf))))
|
|
(deftest
|
|
"make-buffer alias creates a buffer"
|
|
(let ((b (make-buffer))) (assert (buffer? b))))
|
|
(deftest
|
|
"buffer-append! with string"
|
|
(let ((b (make-buffer)))
|
|
(buffer-append! b "hello")
|
|
(buffer-append! b " ")
|
|
(buffer-append! b "world")
|
|
(assert= "hello world" (buffer->string b))))
|
|
(deftest
|
|
"buffer-append! coerces non-string values"
|
|
(let ((b (make-buffer)))
|
|
(buffer-append! b "n=")
|
|
(buffer-append! b 42)
|
|
(buffer-append! b ",")
|
|
(buffer-append! b true)
|
|
(buffer-append! b ",")
|
|
(buffer-append! b nil)
|
|
(assert= "n=42,true," (buffer->string b))))
|
|
(deftest
|
|
"buffer-length tracks total length"
|
|
(let ((b (make-buffer)))
|
|
(buffer-append! b "abc")
|
|
(buffer-append! b "de")
|
|
(assert= 5 (buffer-length b))))
|
|
(deftest
|
|
"buffer aliases interop with string-buffer"
|
|
(let ((b (make-buffer)))
|
|
(buffer-append! b "x")
|
|
(string-buffer-append! b "y")
|
|
(assert= "xy" (string-buffer->string b))
|
|
(assert= "xy" (buffer->string b)))))
|