summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Szarmanski2022-09-22 11:16:44 +0200
committerPiotr Szarmanski2022-09-22 11:16:44 +0200
commit4d82ef18a8bb18317be3e089f432f95b6e5dbd4a (patch)
treebfa28af036aeb0f3e41298867c449318675b5a07
parentfdf5daa317c8a97ef8197200403db6f53a8f1777 (diff)
Implement stream-read-byte
-rw-r--r--src/cache.lisp2
-rw-r--r--src/eris-decode.lisp31
-rw-r--r--tests/decode-tests.lisp43
3 files changed, 66 insertions, 10 deletions
diff --git a/src/cache.lisp b/src/cache.lisp
index ad6a0fa..d6bce9c 100644
--- a/src/cache.lisp
+++ b/src/cache.lisp
@@ -42,4 +42,4 @@
(lambda ,lambda-list
(cacher ,cache ,call-list))))))
-(export cached-lambda)
+(export 'cached-lambda)
diff --git a/src/eris-decode.lisp b/src/eris-decode.lisp
index b7575ab..43f8db0 100644
--- a/src/eris-decode.lisp
+++ b/src/eris-decode.lisp
@@ -186,7 +186,7 @@ fetched from a trusted party.")
(setf (pos stream) new-pos
(data buffer) (data (car (last root)))
(pos buffer) (mod new-pos block-size))
- (if (= (- eof (mod eof block-size)) new-pos)
+ (if (< (- eof (mod eof block-size)) new-pos)
(unpad-buffer buffer)
(setf (eof buffer) block-size))))))
@@ -199,23 +199,25 @@ fetched from a trusted party.")
(defun eris-decode (read-capability fetch-function &key (cache-capacity 2048))
- "With a given fetch-function, return a stream that decodes the read-capability.
+ "Using the FETCH-FUNCTION, return a stream that decodes the READ-CAPABILITY.
Fetch-function must be a function with one argument, the reference octet, which
returns a (simple-array (unsigned-byte 8)) containing the block. The block will
be destructively modified, so you MUST provide a fresh array every time. If a
hash-table is used, a (copy-seq) needs to be done on the return value of
-gethash. "
+gethash.
+
+The keyword argument CACHE-CAPACITY indicates the amount of blocks stored in the
+cache."
(with-slots (level block-size root-reference-pair) read-capability
(let* ((get-block (cached-lambda (:cache-class 'lru-cache
:capacity cache-capacity
:table (make-hash-table :size (1+ cache-capacity) :test #'equalp))
(reference key &optional nonce)
(let* ((block (funcall fetch-function reference)))
+ (unless block (error 'missing-block :reference reference))
(hash-check block reference)
- (if block
- (decrypt-block block key nonce)
- (error 'missing-block :reference reference)))))
+ (decrypt-block block key nonce))))
(root (funcall get-block (reference root-reference-pair) (key root-reference-pair) (make-nonce level))))
;; "Implementations MUST verify the key appearing in the read capability
;; if level of encoded content is larger than 0."
@@ -282,10 +284,25 @@ the new position is beyond the end of file.."
(read-to-seq seq buffer :start start :end (if end end (length seq)) :stream stream)))
(defmethod stream-read-byte ((stream eris-decode-stream))
- nil)
+ (when (minusp (pos (buffer stream)))
+ ;; initializes the buffer
+ (reupdate-block stream (pos stream)))
+ (with-slots (position buffer block-size) stream
+ (with-slots (pos eof data) buffer
+ (cond
+ ((eql pos block-size)
+ (setf pos 0)
+ (advance-next-block stream)
+ (stream-read-byte stream))
+ ((eql pos eof)
+ :eof)
+ (t (prog1 (aref data pos)
+ (incf pos)
+ (incf position)))))))
(defmethod stream-element-type ((stream eris-decode-stream))
'(unsigned-byte 8))
(defun eris-file-length (stream)
+ "This is the equivalent of \"file-length\" for eris-decode-stream."
(eof stream))
diff --git a/tests/decode-tests.lisp b/tests/decode-tests.lisp
index 2cd359a..af3edb0 100644
--- a/tests/decode-tests.lisp
+++ b/tests/decode-tests.lisp
@@ -83,8 +83,6 @@
else
do (replace decoded-array buf :start1 (* i s)))))))
-(assert-bytes-read-4096 (make-octets 16383 :element 1) 1024 (4096 4096 4096 4095))
-
(test simple-decoding-1kib
(assert-array-decode (make-octets 1 :element 1) 1024)
(assert-array-decode (make-octets 1023 :element 2) 1024)
@@ -204,3 +202,44 @@
(assert-length (make-array 16384 :element-type '(unsigned-byte 8) :initial-element 2) 1024))
+(defmacro assert-read-byte (array block-size)
+ `(let* ((*table* (make-hash-table :test #'equalp))
+ (array ,array)
+ (read-capability (eris-encode array ,block-size #'hashtable-encode))
+ (decoded-array (make-array (length array) :element-type '(unsigned-byte 8) :fill-pointer 0))
+ (stream (eris-decode read-capability #'hashtable-decode)))
+ (loop for i = (read-byte stream nil :eof)
+ until (eq i :eof)
+ do (vector-push i decoded-array))
+ (is (equalp decoded-array array))))
+
+(test check-read-byte
+ (assert-read-byte (make-octets 1 :element 2) 1024)
+ (assert-read-byte (make-octets 512 :element 2) 1024)
+ (assert-read-byte (make-octets 1023 :element 2) 1024)
+ (assert-read-byte (make-octets 1024 :element 2) 1024)
+ (assert-read-byte (make-octets 16383 :element 2) 1024)
+ (assert-read-byte (make-octets 16384 :element 2) 1024)
+ (assert-read-byte (make-octets 1024 :element 2) 32kib)
+ (assert-read-byte (make-octets 32767 :element 2) 32kib)
+ (assert-read-byte (make-octets 32768 :element 2) 32kib)
+ (assert-read-byte (make-octets 64000 :element 2) 32kib))
+
+(defmacro assert-read-byte-error (array block-size)
+ `(let* ((*table* (make-hash-table :test #'equalp))
+ (array ,array)
+ (read-capability (eris-encode array ,block-size #'hashtable-encode))
+ (stream (eris-decode read-capability #'hashtable-decode)))
+ (signals end-of-file
+ (loop for i = (read-byte stream t)
+ for n = 0 then (incf n)
+ until (eql n (length array))))))
+
+(test read-byte-eof
+ (assert-read-byte-error (make-octets 1 :element 2) 1024)
+ (assert-read-byte-error (make-octets 1024 :element 2) 1024)
+ (assert-read-byte-error (make-octets 16383 :element 2) 1024)
+ (assert-read-byte-error (make-octets 1024 :element 2) 32kib)
+ (assert-read-byte-error (make-octets 32767 :element 2) 32kib)
+ (assert-read-byte-error (make-octets 32768 :element 2) 32kib))
+