~theothornhill/cl-bare

b0f7dded71dceb7822eddf49a7b05c6f3ceb51c5 — Theodor Thornhill 3 years ago a2a343e
Add map aggregate type

Fix the stupid hashmap with function symbols.
3 files changed, 82 insertions(+), 9 deletions(-)

M src/bare.lisp
M src/package.lisp
M tests/bare-tests.lisp
M src/bare.lisp => src/bare.lisp +63 -9
@@ 149,6 149,7 @@ Set this dynamically in the function calling the DATA defbinary.")

;;; Aggregate types


(defun read-optional-type (type stream)
  (when (read-byte stream)
    (read-binary type stream)))


@@ 160,24 161,23 @@ Set this dynamically in the function calling the DATA defbinary.")
        (write-byte 1 stream)
        (write-binary object stream))))


(defun read-array (type stream)
  (let ((size (read-binary 'uint stream))
  (let ((size (slot-value
               (read-binary 'uint stream)
               'value))
        res)
    (with-slots (value) size
      (dotimes (i value)
        (push (read-binary type stream) res)))
    (dotimes (i size)
      (push (read-binary type stream) res))
    (nreverse res)))

(defun write-array (objects stream)
  (let ((size (length objects)))
    (write-binary (read-binary
                   'uint
                   (flex:make-in-memory-input-stream
                    (vector size)))
                  stream)
    (write-binary (make-uint :value size) stream)
    (dotimes (i size)
      (write-binary (nth i objects) stream))))


(defun read-array-fixed (type length stream)
  (let (res)
    (dotimes (i length)


@@ 187,3 187,57 @@ Set this dynamically in the function calling the DATA defbinary.")
(defun write-array-fixed (objects stream)
  (dolist (object objects)
    (write-binary object stream)))


(defparameter *constructors*
  #.(let ((ht (make-hash-table)))
      (loop for (key . value) in
            '((uint . make-uint)
              (u8 . make-u8)
              (u16 . make-u16)
              (u32 . make-u32)
              (u64 . make-u64)

              (int . make-int)
              (i8 . make-i8)
              (i16 . make-i16)
              (i32 . make-i32)
              (i64 . make-i64)

              (f32 . make-f32)
              (f64 . make-f64)

              (bool . make-bool)
              (enum . make-enum)
              (str . make-str)
              (data . make-data)
              (data-fixed . make-data-fixed)
              (void . make-void))
            do (setf (gethash key ht) value))
      ht))

(defun read-map (key-type obj-type stream)
  (let* ((size (slot-value
                (read-binary 'uint stream)
                'value))
         (res (make-hash-table :size size :test 'equalp)))
    (dotimes (i size)
      (let ((key (slot-value
                  (read-binary key-type stream)
                  'value))
            (object (slot-value
                     (read-binary obj-type stream)
                     'value)))
        (setf (gethash key res) object)))
    res))

(defun write-map (key-type obj-type hashmap stream)
  (write-binary (make-uint :value (hash-table-count hashmap)) stream)
  (maphash (lambda (k v)
             (write-binary (funcall
                            (gethash key-type *constructors*)
                            :value k) stream)
             (write-binary (funcall
                            (gethash obj-type *constructors*)
                            :value v) stream))
           hashmap))

M src/package.lisp => src/package.lisp +2 -0
@@ 26,4 26,6 @@
   :write-array
   :read-array-fixed
   :write-array-fixed
   :read-map
   :write-map
   :value))

M tests/bare-tests.lisp => tests/bare-tests.lisp +17 -0
@@ 224,3 224,20 @@
          (ok (= value 51)))
        (with-slots (value) (fourth objects)
          (ok (= value 68)))))))

(deftest map-test
  (testing "reading and writing maps"
    (with-input-from-sequence
        (in
         (with-output-to-sequence (out)
           (write-map 'u8 'u8
            (read-map 'u8 'u8 (buf #(#x03
                                     #x01 #x11
                                     #x02 #x22
                                     #x03 #x33)))
            out)))
      (let ((objects (read-map 'u8 'u8 in)))
        (ok (= 3 (hash-table-count objects)))
        (ok (= (gethash 1 objects) #x11))
        (ok (= (gethash 2 objects) #x22))
        (ok (= (gethash 3 objects) #x33))))))