; lib/artdag/serialize.sx — portable wire form for whole DAGs, so a peer can ; receive and run a graph it did not author. The form is a topo-ordered list of ; node records (id op inputs params commutative) — plain lists with keyword-keyed ; param dicts, which survive write/read (unlike string-keyed node dicts). The id ; is the content-id, so the form is self-verifying. Depends on dag.sx. (define artdag/node->record (fn (dag id) (let ((n (artdag/dag-get dag id))) (list id (artdag/node-op n) (artdag/node-inputs n) (artdag/node-params n) (get n :commutative))))) ; dag -> list of records, in topological order. (define artdag/dag->wire (fn (dag) (map (fn (id) (artdag/node->record dag id)) (artdag/dag-order dag)))) ; an empty input list reads back as nil; normalize it. (define artdag/-rec-inputs (fn (rec) (let ((i (nth rec 2))) (if (nil? i) (list) i)))) (define artdag/-rec->node (fn (rec) {:inputs (artdag/-rec-inputs rec) :commutative (nth rec 4) :op (nth rec 1) :params (nth rec 3)})) ; records -> dag. Local author names are not part of the wire form; the receiver ; works by content-id. :names is left empty. (define artdag/wire->dag (fn (records) (reduce (fn (dag rec) (let ((id (nth rec 0))) {:names (get dag :names) :order (concat (get dag :order) (list id)) :ok true :nodes (assoc (get dag :nodes) id (artdag/-rec->node rec))})) {:names {} :order (list) :ok true :nodes {}} records))) ; integrity: each record's id must equal the content-id recomputed from its spec. (define artdag/wire-verify (fn (records) (every? (fn (rec) (= (nth rec 0) (artdag/content-id (artdag/-rec->node rec)))) records))) ; string transport. (define artdag/dag->string (fn (dag) (write-to-string (artdag/dag->wire dag)))) (define artdag/string->dag (fn (s) (artdag/wire->dag (read (open-input-string s)))))