1 ! Copyright (C) 2006 Adam Langley and Chris Double.
2 ! Adam Langley was the original author of this work.
4 ! Chris Double modified it to fix bugs and get it working
5 ! correctly under the latest versions of Factor.
7 ! See http://factorcode.org/license.txt for BSD license.
9 USING: namespaces sequences kernel math io math.functions
10 io.binary strings classes words sbufs classes.tuple arrays
11 vectors byte-arrays quotations hashtables hashtables.identity
12 assocs help.syntax help.markup splitting io.streams.byte-array
13 io.encodings.string io.encodings.utf8 io.encodings.binary
14 combinators accessors locals prettyprint compiler.units
15 sequences.private classes.tuple.private vocabs ;
18 GENERIC: (serialize) ( obj -- )
22 ! Variable holding a assoc of objects already serialized
25 : add-object ( obj -- )
26 #! Add an object to the sequence of already serialized
28 serialized get [ assoc-size swap ] keep set-at ;
30 : object-id ( obj -- id )
31 #! Return the id of an already serialized object
34 ! Numbers are serialized as follows:
36 ! 1<=x<=126 => B{ x | 0x80 }
37 ! x>127 => B{ length(x) x[0] x[1] ... }
38 ! x>2^1024 => B{ 0xff length(x) x[0] x[1] ... }
39 ! The last case is needed because a very large number would
40 ! otherwise be confused with a small number.
41 : serialize-cell ( n -- )
57 : deserialize-cell ( -- n )
59 { [ dup 0xff = ] [ drop deserialize-cell read be> ] }
60 { [ dup 0x80 >= ] [ 0x80 bitxor ] }
64 : serialize-shared ( obj quot -- )
67 [ CHAR: o write1 serialize-cell drop ]
70 M: f (serialize) ( obj -- )
73 M: integer (serialize) ( obj -- )
77 dup 0 < [ neg CHAR: m ] [ CHAR: p ] if write1
81 M: float (serialize) ( obj -- )
83 double>bits serialize-cell ;
85 : serialize-seq ( obj code -- )
89 [ length serialize-cell ]
90 [ [ (serialize) ] each ] tri
91 ] curry serialize-shared ;
93 M: tuple (serialize) ( obj -- )
96 [ class-of (serialize) ]
98 [ tuple>array rest (serialize) ]
102 M: array (serialize) ( obj -- )
103 CHAR: a serialize-seq ;
105 M: quotation (serialize) ( obj -- )
108 [ >array (serialize) ] [ add-object ] bi
111 M: hashtable (serialize) ( obj -- )
114 [ add-object ] [ >alist (serialize) ] bi
117 M: byte-array (serialize) ( obj -- )
121 [ length serialize-cell ]
125 M: string (serialize) ( obj -- )
131 [ length serialize-cell ]
136 : serialize-true ( word -- )
137 drop CHAR: t write1 ;
139 : serialize-gensym ( word -- )
143 [ def>> (serialize) ]
144 [ props>> (serialize) ]
148 : serialize-word ( word -- )
150 [ name>> (serialize) ]
151 [ vocabulary>> (serialize) ]
154 M: word (serialize) ( obj -- )
156 { [ dup t eq? ] [ serialize-true ] }
157 { [ dup vocabulary>> not ] [ serialize-gensym ] }
161 M: wrapper (serialize) ( obj -- )
163 wrapped>> (serialize) ;
169 : intern-object ( obj -- )
170 deserialized get push ;
172 : deserialize-false ( -- f )
175 : deserialize-true ( -- f )
178 : deserialize-positive-integer ( -- number )
181 : deserialize-negative-integer ( -- number )
182 deserialize-positive-integer neg ;
184 : deserialize-zero ( -- number )
187 : deserialize-float ( -- float )
188 deserialize-cell bits>double ;
190 : (deserialize-string) ( -- string )
191 deserialize-cell read utf8 decode ;
193 : deserialize-string ( -- string )
194 (deserialize-string) dup intern-object ;
196 : deserialize-word ( -- word )
197 (deserialize) (deserialize) 2dup [ require ] keep lookup-word
200 2array unparse "Unknown word: " prepend throw
203 : deserialize-gensym ( -- word )
206 [ (deserialize) define ]
207 [ (deserialize) >>props drop ]
211 : deserialize-wrapper ( -- wrapper )
212 (deserialize) <wrapper> ;
214 :: (deserialize-seq) ( exemplar quot -- seq )
215 deserialize-cell exemplar new-sequence
217 [ [ drop quot call ] map! ] bi ; inline
219 : deserialize-array ( -- array )
220 { } [ (deserialize) ] (deserialize-seq) ;
222 : deserialize-quotation ( -- array )
223 (deserialize) >quotation dup intern-object ;
225 : deserialize-byte-array ( -- byte-array )
226 B{ } [ read1 ] (deserialize-seq) ;
228 : deserialize-hashtable ( -- hashtable )
231 [ (deserialize) assoc-union! drop ]
234 : copy-seq-to-tuple ( seq tuple -- )
235 [ set-array-nth ] curry each-index ;
237 : deserialize-tuple ( -- array )
238 #! Ugly because we have to intern the tuple before reading
244 [ [ copy-seq-to-tuple ] keep ] bi*
247 : deserialize-unknown ( -- object )
248 deserialize-cell deserialized get nth ;
250 : deserialize* ( -- object ? )
253 { CHAR: A [ deserialize-byte-array ] }
254 { CHAR: F [ deserialize-float ] }
255 { CHAR: T [ deserialize-tuple ] }
256 { CHAR: W [ deserialize-wrapper ] }
257 { CHAR: a [ deserialize-array ] }
258 { CHAR: h [ deserialize-hashtable ] }
259 { CHAR: m [ deserialize-negative-integer ] }
260 { CHAR: n [ deserialize-false ] }
261 { CHAR: t [ deserialize-true ] }
262 { CHAR: o [ deserialize-unknown ] }
263 { CHAR: p [ deserialize-positive-integer ] }
264 { CHAR: q [ deserialize-quotation ] }
265 { CHAR: s [ deserialize-string ] }
266 { CHAR: w [ deserialize-word ] }
267 { CHAR: G [ deserialize-word ] }
268 { CHAR: z [ deserialize-zero ] }
274 : (deserialize) ( -- obj )
275 deserialize* [ "End of stream" throw ] unless ;
279 : deserialize ( -- obj )
280 V{ } clone deserialized
281 [ (deserialize) ] with-variable ;
283 : serialize ( obj -- )
284 IH{ } clone serialized [ (serialize) ] with-variable ;
286 : bytes>object ( bytes -- obj )
287 binary [ deserialize ] with-byte-reader ;
289 : object>bytes ( obj -- bytes )
290 binary [ serialize ] with-byte-writer ;