Writing Binary Objects

Generating code to write out an instance of a binary class will proceed similarly. First you can define a write-value generic function.

  1. (defgeneric write-value (type stream value &key)
  2. (:documentation "Write a value as the given type to the stream."))

Then you define a helper function that translates a define-binary-class slot specifier into code that writes out the slot using write-value. As with the slot->read-value function, this helper function needs to take the name of the stream variable as an argument.

  1. (defun slot->write-value (spec stream)
  2. (destructuring-bind (name (type &rest args)) (normalize-slot-spec spec)
  3. `(write-value ',type ,stream ,name ,@args)))

Now you can add a write-value template to the define-binary-class macro.

  1. (defmacro define-binary-class (name slots)
  2. (with-gensyms (typevar objectvar streamvar)
  3. `(progn
  4. (defclass ,name ()
  5. ,(mapcar #'slot->defclass-slot slots))
  6. (defmethod read-value ((,typevar (eql ',name)) ,streamvar &key)
  7. (let ((,objectvar (make-instance ',name)))
  8. (with-slots ,(mapcar #'first slots) ,objectvar
  9. ,@(mapcar #'(lambda (x) (slot->read-value x streamvar)) slots))
  10. ,objectvar))
  11. (defmethod write-value ((,typevar (eql ',name)) ,streamvar ,objectvar &key)
  12. (with-slots ,(mapcar #'first slots) ,objectvar
  13. ,@(mapcar #'(lambda (x) (slot->write-value x streamvar)) slots))))))