(assert-fail (buffer 123)) (assert (void? (path-make-dir "a/new/dir")))(assert (path-exists? "a/new/dir"))(assert (void? (path-make-dir "a/new/dir")))(assert (void? (path-delete "a/new/dir")))(assert (not (path-exists? "a/new/dir")))(assert (void? (path-delete "a/new")))(assert (not (path-exists? "a/new")))(assert (void? (path-delete "a")))(assert (not (path-exists? "a"))) (def b (buffer))(assert (io? b))(assert (eq? (type-of b) 'io))(assert (eq? (io-buffer-mode b) :memory))(assert (= (size-of b) 0)) ; no data(assert (= (io-pos b) 0))(assert (= (io-pos! b 1) 0))(assert (eof? (io-read b 'u8))) ; empty - EOF(assert (io-eof? b))(assert (eof? (io-read b 'u8))) ; still empty - EOF again(assert (io-eof? b));; write one rune(assert (= (io-write b #\¢) 3))(assert (= (size-of b) 3))(assert (= (io-pos b) 3));; go back(assert (= (io-pos! b 0) 0))(assert (not (io-eof? b)));; peek and compare(def x (io-peek b 'rune))(assert (eq? (type-of x) 'rune))(assert (equal? x #\¢))(assert (not (io-eof? b)))(assert (= (io-pos b) 0));; read it back and compare(def x (io-read b 'rune))(assert (eq? (type-of x) 'rune))(assert (equal? x #\¢))(assert (not (io-eof? b)))(assert (eof? (io-read b 'rune)))(assert (io-eof? b))(assert (= (io-pos b) 3));; peek/read as an array of bytes and compare(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'utf8 0) ""))(assert (equal? (io-read b 'utf8 0) ""))(assert (equal? (io-peek b 'rune 0) (arr 'rune)))(assert (equal? (io-read b 'rune 0) (arr 'rune)))(assert (equal? (io-peek b 'u8 3) (arr 'u8 #xef #xbf #xa0)))(assert (equal? (io-read b 'u8 3) (arr 'u8 #xef #xbf #xa0)));; go back and try reading more than there is(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'u8 4) (arr 'u8 #xef #xbf #xa0)))(assert (equal? (io-read b 'u8 4) (arr 'u8 #xef #xbf #xa0)))(assert (not (io-eof? b))) ; not eof until we try and read nothing(assert (eof? (io-read b 'u8 1)))(assert (io-eof? b)) ; _now_ it's eof;; go back and read as an utf8 string(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'utf8) "¢"))(assert (equal? (io-peek b 'rune) #\¢))(assert (equal? (io-read b 'utf8) "¢"));; go back and read as an array of runes(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'rune 1) (arr 'rune #\¢)))(assert (equal? (io-read b 'rune 1) (arr 'rune #\¢)));; skip back and forth(assert (= (io-skip b -1) 2))(assert (= (io-pos b) 2))(assert (= (io-skip b -1) 1))(assert (= (io-pos b) 1))(assert (= (io-skip b -2 :end T) 1))(assert (= (io-pos b) 1))(assert (= (io-skip b -3 :end T) 0))(assert (= (io-pos b) 0))(assert (equal? (io-peek b 'utf8) "¢"))(assert (equal? (io-peek b 'rune) #\¢))(assert (equal? (io-read b 'rune) #\¢));; convert to string - destructive operation(assert (= (io-pos! b 0) 0))(assert (equal? (io->str b) "¢"))(assert (= (io-pos b) 0))(assert (= (io-pos! b 9) 0))(assert (= (size-of b) 0));; filename(assert (equal? (io-filename b) ""))(assert (equal? (io-filename! b "hi") "hi"))(assert (equal? (io-filename b) "hi"));; write some more(assert (= (io-write b "hello") 5));; truncate(assert (void? (io-truncate b 3))) ; shrinking(assert (= (size-of b) 3))(assert (= (io-pos b) 3))(assert (void? (io-truncate b 0))) ; emptying(assert (eof? (io-read b 'u8)))(assert (io-eof? b))(assert (= (size-of b) 0))(assert (= (io-pos b) 0))(assert (= (io-pos! b 1) 0))(assert (eof? (io-read b 'u8)))(assert (io-eof? b));; closed from now on(assert (void? (io-close b)));; can close again without errors - noop(assert (void? (io-close b)));; filename still usable(assert (equal? (io-filename b) "hi"))(assert (equal? (io-filename! b "no") "no"))(assert (equal? (io-filename b) "no"));; can't do much(assert-fail (io->str b) io-error)(assert-fail (io-buffer-mode b) io-error)(assert-fail (io-buffer-mode! b NIL) io-error)(assert-fail (io-eof? b) io-error)(assert-fail (io-peek b 'rune) io-error)(assert-fail (io-pos b) io-error)(assert-fail (io-pos! b 0) io-error)(assert-fail (io-read b 'u8) io-error)(assert-fail (io-read-all b) io-error)(assert-fail (io-read-line b) io-error)(assert-fail (io-read-lines b) io-error)(assert-fail (io-read-until b #\x) io-error)(assert-fail (io-skip b 0) io-error)(assert-fail (io-truncate b 0) io-error)(assert-fail (io-write b "") io-error) (def b (buffer));; write an array of runes(assert (= (io-write b (arr 'rune #\¡ #\¿ #\nul #\x #\y #\z)) 8))(assert (= (io-pos! b 0) 0));; peek/read back as an utf8 string, 3 runes total(assert (equal? (io-peek b 'utf8 3) "¡¿\x00"))(assert (equal? (io-peek b 'rune 3) #arr(rune #\¡ #\¿ #\nul)))(assert (equal? (io-read b 'utf8 3) "¡¿\x00"))(assert (= (io-pos! b 0) 0));; now peek a rune(assert (equal? (io-peek b 'rune) #\¡))(assert (equal? (io-peek b 'rune) #\¡));; read until #\nul(assert (equal? (io-read-until b #\nul) "¡¿\x00"));; read the rest as a line(assert (equal? (io-read-line b) "xyz"));; nothing left(assert (equal? (io-read-all b) ""))(assert (eof? (io-read b 'u8))) ;; path-cwd(assert (str? (path-cwd)))(assert (path-cwd "."))(assert-fail (path-cwd "." ".") arity-error)(assert-fail (path-cwd "does/not/exist") io-error) ;; path-exists? + path-rename + path-delete(assert (path-exists? "."))(assert (not (path-exists? "doesnotexist.txt")))(assert-fail (path-delete "doesnotexist.txt") io-error)(def f (file "doesexist.txt" #o644 :write :create :truncate))(assert (io? f))(assert (path-exists? "doesexist.txt"))(assert-fail (io-read f 'u8) io-error) ; read on write-only(io-close f)(assert (path-exists? "doesexist.txt"))(assert-fail (file "doesexist.txt" :write :create :truncate :exclusive) io-error)(def f (file "doesexist.txt"))(assert (io? f))(assert-fail (io-write f (u8 0)) io-error) ; write on read-only(assert (eof? (io-read f 'u8)))(assert (void? (io-close f)))(assert-fail (path-rename "doesnotexist.txt" "moved.txt"))(assert (path-rename "doesexist.txt" "moved.txt"))(assert (not (path-exists? "doesexist.txt")))(assert (path-exists? "moved.txt"))(assert (path-delete "moved.txt"))(assert (not (path-exists? "doesexist.txt")))(assert-fail (path-delete "moved.txt")) (def lines '("12345 абвгд weoiwhefohwefoihweoifh wefiweu3209u092039 jhksjdvksdjvbksdvb qwhqhfohwefe weofhweofhoiewhfoiwhefh\n" "hello, world!\n" "\n" "\n" "x"))(def data (apply str lines))(def f (file "test.txt" :write :create :append :truncate))(assert (io? f))(assert (eq? (io-buffer-mode f) :block))(assert-fail (io-buffer-mode!))(assert-fail (io-buffer-mode! f))(assert-fail (io-buffer-mode! f 'blah))(io-buffer-mode! f :memory)(assert (eq? (io-buffer-mode! f :block) :block))(assert (eq? (io-buffer-mode f) :block))(assert (eq? (io-buffer-mode! f :line) :line))(assert (eq? (io-buffer-mode f) :line))(assert (eq? (io-buffer-mode! f NIL) NIL))(assert (eq? (io-buffer-mode f) NIL))(assert (eq? (io-buffer-mode! f :line) :line))(assert (= (io-write f data) (size-of data)))(def f2 (file "test.txt"))(assert (= (io-skip f2 0 :end T) (1- (size-of data))))(assert (io-flush f))(assert (= (io-skip f2 0 :end T) (size-of data)))(assert (void? (io-close f2)))(assert (void? (io-close f)))(def f (file "test.txt" :read))(assert (io? f))(assert (equal? (io-read-lines f) lines))(assert (= (io-line f) 5))(assert (= (io-column f) 1))(assert (= (io-pos! f 0) 0))(assert (equal? (io-read-all f) data))(assert (= (io-line f) 5))(assert (= (io-column f) 1))(assert-fail (io-truncate f 0))(assert (void? (io-close f)))(assert (void? (path-delete "test.txt"))) ;; endian-specific read/write(def b (buffer))(assert (= (io-write b (arr 'u32 #x44556677 #xa001ed0f) :big-endian) 8))(assert (= (io-pos! b 0) 0))(assert (= (io-peek b 'u64 :big-endian) #x44556677a001ed0f))(assert (= (io-read b 'u64 :big-endian) #x44556677a001ed0f))(assert (= (io-pos! b 0) 0))(assert (= (io-peek b 'u64 :little-endian) #x0fed01a077665544))(assert (= (io-read b 'u64 :little-endian) #x0fed01a077665544))(assert (= (io-pos! b 0) 0))(assert (= (io-peek b 'u32 :big-endian) #x44556677))(assert (= (io-read b 'u32 :big-endian) #x44556677))(assert (= (io-pos! b 0) 0))(assert (= (io-peek b 'u32 :little-endian) #x77665544))(assert (= (io-read b 'u32 :little-endian) #x77665544))(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'u32 1 :big-endian) (arr 'u32 #xa44556677)))(assert (equal? (io-read b 'u32 1 :big-endian) (arr 'u32 #xa44556677)))(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'u32 1 :little-endian) (arr 'u32 #x77665544)))(assert (equal? (io-read b 'u32 1 :little-endian) (arr 'u32 #x77665544)))(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'u16 2 :big-endian) (arr 'u16 #x4455 #x6677)))(assert (equal? (io-read b 'u16 2 :big-endian) (arr 'u16 #x4455 #x6677)))(assert (= (io-pos! b 0) 0))(assert (equal? (io-peek b 'u16 2 :little-endian) (arr 'u16 #x5544 #x7766)))(assert (equal? (io-read b 'u16 2 :little-endian) (arr 'u16 #x5544 #x7766))) ;; aref/aset!/length with an in-memory io(def x (aref b 0))(assert (= x #x44))(assert (eq? (type-of x) 'u8))(aset! b 2 #x1234)(def x (aref b 2))(assert (= x #x34))(assert (= (length b) 8))(assert-fail (aset! b 8 0) bounds-error)(assert-fail (aref b 8) bounds-error)(assert-fail (aset! b -1 0) arg-error)(assert-fail (aref b -1) arg-error) ;; evaluate during read(def b (buffer))(io-filename! b "buffer")(io-write b "#fn(unbound-symbol)")(io-pos! b 0)(assert-fail (read b) unbound-error) ;; read-only buffering of underlying data(def a "hello")(def b (buffer a))(assert-fail (io-truncate b 0)) ; read-only - no truncation(io-discard-buffer b) ; should be a no-op(assert (equal? (io-peek b 'rune) #\h))(assert (equal? (io-read-all b) a))(assert (eof? (io-peek b 'rune)))(assert (io-eof? b))(def b (buffer (u16 #x1111)))(gc)(io-discard-buffer b) ; should be a no-op(assert (= (io-read b 'u16) #x1111))(def b (buffer (arr 'f32 1.0 2.0 3.0 -4.0)))(gc)(io-discard-buffer b) ; should be a no-op(io-pos! b 8)(assert (equal? (io-peek b 'p32 3) #arr(p32 #x40400000 #xC0800000)))(gc)(gc)(assert (equal? (io-read b 'p32 3) #arr(p32 #x40400000 #xC0800000)))(def b2 (buffer b :start 8 :end 12)) ; buffer on buffer(gc)(assert (equal? (io-peek b2 'p32 2) #arr(p32 #x40400000)))(gc)(assert (equal? (io-read b2 'p32 2) #arr(p32 #x40400000)))
(assert-fail (buffer 123))
(assert (void? (path-make-dir "a/new/dir")))
(assert (path-exists? "a/new/dir"))
(assert (void? (path-make-dir "a/new/dir")))
(assert (void? (path-delete "a/new/dir")))
(assert (not (path-exists? "a/new/dir")))
(assert (void? (path-delete "a/new")))
(assert (not (path-exists? "a/new")))
(assert (void? (path-delete "a")))
(assert (not (path-exists? "a")))
(def b (buffer))
(assert (io? b))
(assert (eq? (type-of b) 'io))
(assert (eq? (io-buffer-mode b) :memory))
(assert (= (size-of b) 0)) ; no data
(assert (= (io-pos b) 0))
(assert (= (io-pos! b 1) 0))
(assert (eof? (io-read b 'u8))) ; empty - EOF
(assert (io-eof? b))
(assert (eof? (io-read b 'u8))) ; still empty - EOF again
(assert (io-eof? b))
;; write one rune
(assert (= (io-write b #\¢) 3))
(assert (= (size-of b) 3))
(assert (= (io-pos b) 3))
;; go back
(assert (= (io-pos! b 0) 0))
(assert (not (io-eof? b)))
;; peek and compare
(def x (io-peek b 'rune))
(assert (eq? (type-of x) 'rune))
(assert (equal? x #\¢))
(assert (not (io-eof? b)))
(assert (= (io-pos b) 0))
;; read it back and compare
(def x (io-read b 'rune))
(assert (eq? (type-of x) 'rune))
(assert (equal? x #\¢))
(assert (not (io-eof? b)))
(assert (eof? (io-read b 'rune)))
(assert (io-eof? b))
(assert (= (io-pos b) 3))
;; peek/read as an array of bytes and compare
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'utf8 0) ""))
(assert (equal? (io-read b 'utf8 0) ""))
(assert (equal? (io-peek b 'rune 0) (arr 'rune)))
(assert (equal? (io-read b 'rune 0) (arr 'rune)))
(assert (equal? (io-peek b 'u8 3) (arr 'u8 #xef #xbf #xa0)))
(assert (equal? (io-read b 'u8 3) (arr 'u8 #xef #xbf #xa0)))
;; go back and try reading more than there is
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'u8 4) (arr 'u8 #xef #xbf #xa0)))
(assert (equal? (io-read b 'u8 4) (arr 'u8 #xef #xbf #xa0)))
(assert (not (io-eof? b))) ; not eof until we try and read nothing
(assert (eof? (io-read b 'u8 1)))
(assert (io-eof? b)) ; _now_ it's eof
;; go back and read as an utf8 string
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'utf8) "¢"))
(assert (equal? (io-peek b 'rune) #\¢))
(assert (equal? (io-read b 'utf8) "¢"))
;; go back and read as an array of runes
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'rune 1) (arr 'rune #\¢)))
(assert (equal? (io-read b 'rune 1) (arr 'rune #\¢)))
;; skip back and forth
(assert (= (io-skip b -1) 2))
(assert (= (io-pos b) 2))
(assert (= (io-skip b -1) 1))
(assert (= (io-pos b) 1))
(assert (= (io-skip b -2 :end T) 1))
(assert (= (io-pos b) 1))
(assert (= (io-skip b -3 :end T) 0))
(assert (= (io-pos b) 0))
(assert (equal? (io-peek b 'utf8) "¢"))
(assert (equal? (io-peek b 'rune) #\¢))
(assert (equal? (io-read b 'rune) #\¢))
;; convert to string - destructive operation
(assert (= (io-pos! b 0) 0))
(assert (equal? (io->str b) "¢"))
(assert (= (io-pos b) 0))
(assert (= (io-pos! b 9) 0))
(assert (= (size-of b) 0))
;; filename
(assert (equal? (io-filename b) ""))
(assert (equal? (io-filename! b "hi") "hi"))
(assert (equal? (io-filename b) "hi"))
;; write some more
(assert (= (io-write b "hello") 5))
;; truncate
(assert (void? (io-truncate b 3))) ; shrinking
(assert (= (size-of b) 3))
(assert (= (io-pos b) 3))
(assert (void? (io-truncate b 0))) ; emptying
(assert (eof? (io-read b 'u8)))
(assert (io-eof? b))
(assert (= (size-of b) 0))
(assert (= (io-pos b) 0))
(assert (= (io-pos! b 1) 0))
(assert (eof? (io-read b 'u8)))
(assert (io-eof? b))
;; closed from now on
(assert (void? (io-close b)))
;; can close again without errors - noop
(assert (void? (io-close b)))
;; filename still usable
(assert (equal? (io-filename b) "hi"))
(assert (equal? (io-filename! b "no") "no"))
(assert (equal? (io-filename b) "no"))
;; can't do much
(assert-fail (io->str b) io-error)
(assert-fail (io-buffer-mode b) io-error)
(assert-fail (io-buffer-mode! b NIL) io-error)
(assert-fail (io-eof? b) io-error)
(assert-fail (io-peek b 'rune) io-error)
(assert-fail (io-pos b) io-error)
(assert-fail (io-pos! b 0) io-error)
(assert-fail (io-read b 'u8) io-error)
(assert-fail (io-read-all b) io-error)
(assert-fail (io-read-line b) io-error)
(assert-fail (io-read-lines b) io-error)
(assert-fail (io-read-until b #\x) io-error)
(assert-fail (io-skip b 0) io-error)
(assert-fail (io-truncate b 0) io-error)
(assert-fail (io-write b "") io-error)
(def b (buffer))
;; write an array of runes
(assert (= (io-write b (arr 'rune #\¡ #\¿ #\nul #\x #\y #\z)) 8))
(assert (= (io-pos! b 0) 0))
;; peek/read back as an utf8 string, 3 runes total
(assert (equal? (io-peek b 'utf8 3) "¡¿\x00"))
(assert (equal? (io-peek b 'rune 3) #arr(rune #\¡ #\¿ #\nul)))
(assert (equal? (io-read b 'utf8 3) "¡¿\x00"))
(assert (= (io-pos! b 0) 0))
;; now peek a rune
(assert (equal? (io-peek b 'rune) #\¡))
(assert (equal? (io-peek b 'rune) #\¡))
;; read until #\nul
(assert (equal? (io-read-until b #\nul) "¡¿\x00"))
;; read the rest as a line
(assert (equal? (io-read-line b) "xyz"))
;; nothing left
(assert (equal? (io-read-all b) ""))
(assert (eof? (io-read b 'u8)))
;; path-cwd
(assert (str? (path-cwd)))
(assert (path-cwd "."))
(assert-fail (path-cwd "." ".") arity-error)
(assert-fail (path-cwd "does/not/exist") io-error)
;; path-exists? + path-rename + path-delete
(assert (path-exists? "."))
(assert (not (path-exists? "doesnotexist.txt")))
(assert-fail (path-delete "doesnotexist.txt") io-error)
(def f (file "doesexist.txt" #o644 :write :create :truncate))
(assert (io? f))
(assert (path-exists? "doesexist.txt"))
(assert-fail (io-read f 'u8) io-error) ; read on write-only
(io-close f)
(assert (path-exists? "doesexist.txt"))
(assert-fail (file "doesexist.txt" :write :create :truncate :exclusive) io-error)
(def f (file "doesexist.txt"))
(assert (io? f))
(assert-fail (io-write f (u8 0)) io-error) ; write on read-only
(assert (eof? (io-read f 'u8)))
(assert (void? (io-close f)))
(assert-fail (path-rename "doesnotexist.txt" "moved.txt"))
(assert (path-rename "doesexist.txt" "moved.txt"))
(assert (not (path-exists? "doesexist.txt")))
(assert (path-exists? "moved.txt"))
(assert (path-delete "moved.txt"))
(assert (not (path-exists? "doesexist.txt")))
(assert-fail (path-delete "moved.txt"))
(def lines '("12345 абвгд weoiwhefohwefoihweoifh wefiweu3209u092039 jhksjdvksdjvbksdvb qwhqhfohwefe weofhweofhoiewhfoiwhefh\n"
"hello, world!\n"
"\n"
"\n"
"x"))
(def data (apply str lines))
(def f (file "test.txt" :write :create :append :truncate))
(assert (io? f))
(assert (eq? (io-buffer-mode f) :block))
(assert-fail (io-buffer-mode!))
(assert-fail (io-buffer-mode! f))
(assert-fail (io-buffer-mode! f 'blah))
(io-buffer-mode! f :memory)
(assert (eq? (io-buffer-mode! f :block) :block))
(assert (eq? (io-buffer-mode f) :block))
(assert (eq? (io-buffer-mode! f :line) :line))
(assert (eq? (io-buffer-mode f) :line))
(assert (eq? (io-buffer-mode! f NIL) NIL))
(assert (eq? (io-buffer-mode f) NIL))
(assert (eq? (io-buffer-mode! f :line) :line))
(assert (= (io-write f data) (size-of data)))
(def f2 (file "test.txt"))
(assert (= (io-skip f2 0 :end T) (1- (size-of data))))
(assert (io-flush f))
(assert (= (io-skip f2 0 :end T) (size-of data)))
(assert (void? (io-close f2)))
(assert (void? (io-close f)))
(def f (file "test.txt" :read))
(assert (io? f))
(assert (equal? (io-read-lines f) lines))
(assert (= (io-line f) 5))
(assert (= (io-column f) 1))
(assert (= (io-pos! f 0) 0))
(assert (equal? (io-read-all f) data))
(assert (= (io-line f) 5))
(assert (= (io-column f) 1))
(assert-fail (io-truncate f 0))
(assert (void? (io-close f)))
(assert (void? (path-delete "test.txt")))
;; endian-specific read/write
(def b (buffer))
(assert (= (io-write b (arr 'u32 #x44556677 #xa001ed0f) :big-endian) 8))
(assert (= (io-pos! b 0) 0))
(assert (= (io-peek b 'u64 :big-endian) #x44556677a001ed0f))
(assert (= (io-read b 'u64 :big-endian) #x44556677a001ed0f))
(assert (= (io-pos! b 0) 0))
(assert (= (io-peek b 'u64 :little-endian) #x0fed01a077665544))
(assert (= (io-read b 'u64 :little-endian) #x0fed01a077665544))
(assert (= (io-pos! b 0) 0))
(assert (= (io-peek b 'u32 :big-endian) #x44556677))
(assert (= (io-read b 'u32 :big-endian) #x44556677))
(assert (= (io-pos! b 0) 0))
(assert (= (io-peek b 'u32 :little-endian) #x77665544))
(assert (= (io-read b 'u32 :little-endian) #x77665544))
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'u32 1 :big-endian) (arr 'u32 #xa44556677)))
(assert (equal? (io-read b 'u32 1 :big-endian) (arr 'u32 #xa44556677)))
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'u32 1 :little-endian) (arr 'u32 #x77665544)))
(assert (equal? (io-read b 'u32 1 :little-endian) (arr 'u32 #x77665544)))
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'u16 2 :big-endian) (arr 'u16 #x4455 #x6677)))
(assert (equal? (io-read b 'u16 2 :big-endian) (arr 'u16 #x4455 #x6677)))
(assert (= (io-pos! b 0) 0))
(assert (equal? (io-peek b 'u16 2 :little-endian) (arr 'u16 #x5544 #x7766)))
(assert (equal? (io-read b 'u16 2 :little-endian) (arr 'u16 #x5544 #x7766)))
;; aref/aset!/length with an in-memory io
(def x (aref b 0))
(assert (= x #x44))
(assert (eq? (type-of x) 'u8))
(aset! b 2 #x1234)
(def x (aref b 2))
(assert (= x #x34))
(assert (= (length b) 8))
(assert-fail (aset! b 8 0) bounds-error)
(assert-fail (aref b 8) bounds-error)
(assert-fail (aset! b -1 0) arg-error)
(assert-fail (aref b -1) arg-error)
;; evaluate during read
(def b (buffer))
(io-filename! b "buffer")
(io-write b "#fn(unbound-symbol)")
(io-pos! b 0)
(assert-fail (read b) unbound-error)
;; read-only buffering of underlying data
(def a "hello")
(def b (buffer a))
(assert-fail (io-truncate b 0)) ; read-only - no truncation
(io-discard-buffer b) ; should be a no-op
(assert (equal? (io-peek b 'rune) #\h))
(assert (equal? (io-read-all b) a))
(assert (eof? (io-peek b 'rune)))
(assert (io-eof? b))
(def b (buffer (u16 #x1111)))
(gc)
(io-discard-buffer b) ; should be a no-op
(assert (= (io-read b 'u16) #x1111))
(def b (buffer (arr 'f32 1.0 2.0 3.0 -4.0)))
(gc)
(io-discard-buffer b) ; should be a no-op
(io-pos! b 8)
(assert (equal? (io-peek b 'p32 3) #arr(p32 #x40400000 #xC0800000)))
(gc)
(gc)
(assert (equal? (io-read b 'p32 3) #arr(p32 #x40400000 #xC0800000)))
(def b2 (buffer b :start 8 :end 12)) ; buffer on buffer
(gc)
(assert (equal? (io-peek b2 'p32 2) #arr(p32 #x40400000)))
(gc)
(assert (equal? (io-read b2 'p32 2) #arr(p32 #x40400000)))