summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--org-ckons-serializable.asd37
-rw-r--r--src/generics.lisp16
-rw-r--r--src/package.lisp7
-rw-r--r--src/serializable.lisp38
4 files changed, 98 insertions, 0 deletions
diff --git a/org-ckons-serializable.asd b/org-ckons-serializable.asd
new file mode 100644
index 0000000..071b560
--- /dev/null
+++ b/org-ckons-serializable.asd
@@ -0,0 +1,37 @@
+;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
+(declaim (optimize (speed 0) (safety 3) (debug 3)))
+
+(in-package :cl)
+
+(defpackage :org-ckons-serializable-system (:use :cl :asdf))
+(in-package :org-ckons-serializable-system)
+
+(defmacro do-defsystem (&key name version maintainer author description long-description depends-on components)
+ `(defsystem ,name
+ :name ,name
+ :version ,version
+ :maintainer ,maintainer
+ :author ,author
+ :description ,description
+ :long-description ,long-description
+ :depends-on ,(eval depends-on)
+ :components ,components))
+
+(defparameter *quicklisp-packages* '())
+(defparameter *asdf-packages* '(org-ckons-core))
+(defparameter *all-packages* (append *quicklisp-packages* *asdf-packages*))
+
+(loop for pkg in *quicklisp-packages* do
+ (ql:quickload (symbol-name pkg)))
+
+(do-defsystem :name "org-ckons-serializable"
+ :version "1"
+ :maintainer "Carlos Konstanski <me@ckons.org>"
+ :author "Carlos Konstanski <me@ckons.org>"
+ :description "org-ckons-serializable"
+ :long-description "org-ckons-serializable is a library which provides HTML rendering functionality and a drakma HTTP client wrapper."
+ :depends-on *all-packages*
+ :components ((:module src
+ :components ((:file "package")
+ (:file "generics" :depends-on ("package"))
+ (:file "serializable" :depends-on ("generics"))))))
diff --git a/src/generics.lisp b/src/generics.lisp
new file mode 100644
index 0000000..3c3bb8a
--- /dev/null
+++ b/src/generics.lisp
@@ -0,0 +1,16 @@
+;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
+(declaim (optimize (speed 0) (safety 3) (debug 3)))
+
+(in-package :org-ckons-serializable)
+
+(defgeneric all-slots-value-list-no-nulls (serializable)
+ (:documentation "Returns all slots of `record' as an alist. Not
+ limited to field slots."))
+
+(defgeneric all-slots-plist-no-nulls (serializable)
+ (:documentation "Returns all slots of `record' as a plist. Not
+limited to field slots."))
+
+(defgeneric serialize (serializable &key package-name)
+ (:documentation "Returns a string that, when read with
+`read-from-string', will instantiate the `seializable' object."))
diff --git a/src/package.lisp b/src/package.lisp
new file mode 100644
index 0000000..a7b0170
--- /dev/null
+++ b/src/package.lisp
@@ -0,0 +1,7 @@
+;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
+(declaim (optimize (speed 0) (safety 3) (debug 3)))
+
+(defpackage :org-ckons-serializable
+ (:use :cl))
+
+(in-package :org-ckons-serializable)
diff --git a/src/serializable.lisp b/src/serializable.lisp
new file mode 100644
index 0000000..0de2d3c
--- /dev/null
+++ b/src/serializable.lisp
@@ -0,0 +1,38 @@
+;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
+(declaim (optimize (speed 0) (safety 3) (debug 3)))
+
+(in-package :org-ckons-serializable)
+
+(defclass serializable ()
+ ()
+ (:documentation "Provides class serialization and deserialization."))
+
+(defmacro with-all-slots-to-list (serializable &body body)
+ "Iterates over all the slots of `serializable' and builds an alist
+based on those slots."
+ `(remove-if 'null (mapcar (lambda (slot)
+ ,@body)
+ (org-ckons-core::map-slot-names ,serializable))))
+
+(defmethod all-slots-value-list-no-nulls ((serializable serializable))
+ (with-all-slots-to-list serializable
+ (when (slot-value serializable slot)
+ `(,slot . ,(slot-value serializable slot)))))
+
+(defmethod all-slots-plist-no-nulls ((serializable serializable))
+ (let ((slot-plist ()))
+ (loop for slot in (all-slots-value-list-no-nulls serializable) do
+ (setf slot-plist (append slot-plist `(,(intern (format nil "~a" (car slot)) :keyword) ,(cdr slot)))))
+ slot-plist))
+
+(defmethod serialize ((serializable serializable) &key (package-name (package-name #.*package*)))
+ (let ((output (make-array '(0) :element-type 'character :fill-pointer 0 :adjustable t)))
+ (with-output-to-string (stream output)
+ (loop for field in (all-slots-plist-no-nulls serializable) do
+ (princ " " stream)
+ (prin1 field stream)))
+ (format nil "(make-instance '~a::~a~a)" (string-upcase package-name) (type-of serializable) output)))
+
+(defun deserialize (form)
+ "`form' is a string representation of a `make-instance' form."
+ (eval (read-from-string form)))