Simple and fast marshalling of all kinds of Lisp data structures. Convert any object into a s-expression, put it on a stream an revive it from there. Only minimal changes required to make your CLOS objects serializable. Actually you only need to add 1 method per baseclass.
Serialization of simple data
$ (ms:marshal (list 1 2 3 "Foo" "Bar" (make-array '(3) :initial-contents '(a b c)))) --> (:PCODE 1 (:LIST 1 1 2 3 (:SIMPLE-STRING 2 "Foo") (:SIMPLE-STRING 3 "Bar") (:ARRAY 4 (3) T (A B C))))
$ (ms:unmarshal '(:PCODE 1 (:LIST 1 1 2 3 (:SIMPLE-STRING 2 "Foo") (:SIMPLE-STRING 3 "Bar") (:ARRAY 4 (3) T (A B C))))) --> (1 2 3 "Foo" "Bar" #(A B C))
That means that a
(ms:unmarshal (ms:marshal myobject))
returns a deep clone of myobject.
Objects: A more complex example
(defclass ship () ((name :initform "" :initarg :name :accessor name) (dimensions :initform '(:width 0 :length 0) :initarg :dimensions :accessor dimensions) (course :initform 0 :initarg :course :accessor course) (cruise :initform 0 :initarg :cruise :accessor cruise) ; shall be transient (dinghy :initform NIL :initarg :dinghy :accessor dinghy :initarg :dinghy)) ; another ship -> ref (:documentation "A democlass. Some 'persistant slots', one transient. Some numbers, string, lists and object references.")) (defparameter ark (make-instance 'ship :name "Ark" :course 360 :dimensions '(:width 30 :length 90)))
Nothing happens if we try to serialize this, as one important piece is missing:
$ (ms:marshal ark) --> (:PCODE 1 NIL)
For your classes you need to add one special method:
There you are going to define the slots that shall be serialized, so that you can have persistant and transient slots in your class.
(defmethod ms:class-persistant-slots ((self ship)) '(name dimensions course dinghy))
Note that the slot cruise is not listed. Therefore it will not be serialized.
$ (ms:marshal ark) --> (:PCODE 1 (:OBJECT 1 SHIP (:SIMPLE-STRING 2 "Ark") (:LIST 3 :WIDTH 30 :LENGTH 90) 360 (:LIST 4)))
Fine. Try a
(ms:unmarshal (ms:marshal ark))
and you will get a clone of the object ark. The whole thing works with arrays, hashtables, lists, classes/objects, subclasses incl. multiple inheritance, all of this nested and with circular references. See README.md for more detailed examples.