1 import Base 2 import ./decode_data.bend as D 3 import ./entity_key.bend as Key 4 import ./snapshot_data.bend as Snapshot 5 import ./restore_raw.bend as Basic 6 import ./restore_raw_number.bend as Number 7 import ./restore_graph_data.bend as Graph 8 9 type Parsed is Data: 10 Accepted{snapshot:Graph.Snapshot} 11 Rejected{original:D.Raw,error:Basic.Error} 12 def keys_tail(head:Key.Key,result:Basic.Decoded>) -> Basic.Decoded>: 13 match result: 14 case Basic.Value{tail}:Basic.Value{head <> tail} 15 case Basic.Failed{error}:Basic.Failed{error} 16 def keys_head(next:Unit -> Basic.Decoded>,result:Basic.Decoded) -> Basic.Decoded>: 17 match result: 18 case Basic.Value{head}:keys_tail(head,next(Unit{})) 19 case Basic.Failed{error}:Basic.Failed{error} 20 def keys(+path:String,values:List<&2,D.Raw>,+index:U32) -> Basic.Decoded>: 21 match values: 22 case []:Basic.Value{[]} 23 case raw <> rest:keys_head((_ => keys(path,rest,U32.add(index,1))),Basic.key(path ++ "[" ++ U32.show(index) ++ "]",raw)) 24 def group_sources(target:Key.Key,result:Basic.Decoded>) -> Basic.Decoded: 25 match result: 26 case Basic.Value{sources}:Basic.Value{Graph.Group{target,sources}} 27 case Basic.Failed{error}:Basic.Failed{error} 28 def group_target(path:String,raw:D.Raw,result:Basic.Decoded) -> Basic.Decoded: 29 match raw result: 30 case _ Basic.Failed{error}:Basic.Failed{error} 31 case D.Array{sources} Basic.Value{target}:group_sources(target,keys(path,sources,0)) 32 case other Basic.Value{_}:Basic.invalid(~Graph.Group,path,"array",other) 33 def group(+path:String,raw:D.Raw) -> Basic.Decoded: 34 match raw: 35 case D.Array{[target,sources]}:group_target(path ++ "[1]",sources,Basic.key(path ++ "[0]",target)) 36 case other:Basic.invalid(~Graph.Group,path,"target/sources pair",other) 37 def groups_tail(head:Graph.Group,result:Basic.Decoded>) -> Basic.Decoded>: 38 match result: 39 case Basic.Value{tail}:Basic.Value{head <> tail} 40 case Basic.Failed{error}:Basic.Failed{error} 41 def groups_head(next:Unit -> Basic.Decoded>,result:Basic.Decoded) -> Basic.Decoded>: 42 match result: 43 case Basic.Value{head}:groups_tail(head,next(Unit{})) 44 case Basic.Failed{error}:Basic.Failed{error} 45 def groups(+path:String,values:List<&2,D.Raw>,+index:U32) -> Basic.Decoded>: 46 match values: 47 case []:Basic.Value{[]} 48 case raw <> rest:groups_head((_ => groups(path,rest,U32.add(index,1))),group(path ++ "[" ++ U32.show(index) ++ "]",raw)) 49 def relation_groups(name:String,result:Basic.Decoded>) -> Basic.Decoded: 50 match result: 51 case Basic.Value{values}:Basic.Value{Graph.Relation{name,values}} 52 case Basic.Failed{error}:Basic.Failed{error} 53 def relation(+name:String,raw:D.Raw) -> Basic.Decoded: 54 match raw: 55 case D.Array{values}:relation_groups(name,groups("$.relations." ++ name,values,0)) 56 case other:Basic.invalid(~Graph.Relation,"$.relations." ++ name,"array",other) 57 def relations_tail(head:Graph.Relation,result:Basic.Decoded>) -> Basic.Decoded>: 58 match result: 59 case Basic.Value{tail}:Basic.Value{head <> tail} 60 case Basic.Failed{error}:Basic.Failed{error} 61 def relations_head(next:Unit -> Basic.Decoded>,result:Basic.Decoded) -> Basic.Decoded>: 62 match result: 63 case Basic.Value{head}:relations_tail(head,next(Unit{})) 64 case Basic.Failed{error}:Basic.Failed{error} 65 def relations(fields:List<&2,D.Field>) -> Basic.Decoded>: 66 match fields: 67 case []:Basic.Value{[]} 68 case D.Field{name,raw} <> rest:relations_head((_ => relations(rest)),relation(name,raw)) 69 def machines(basic:Snapshot.Snapshot,relations:List<&2,Graph.Relation>,raw:D.Raw) -> Basic.Decoded: 70 match raw: 71 case D.Object{fields}:Basic.Value{Graph.Snapshot{basic,relations,fields}} 72 case other:Basic.invalid(~Graph.Snapshot,"$.machines","object",other) 73 def resources(next:U32,entities:List<&2,Snapshot.Entity>,relations:List<&2,Graph.Relation>,+fields:List<&2,D.Field>,raw:D.Raw) -> Basic.Decoded: 74 match raw: 75 case D.Object{values}:machines(Snapshot.Snapshot{1,next,entities,values},relations,D.field("machines",fields)) 76 case other:Basic.invalid(~Graph.Snapshot,"$.resources","object",other) 77 def relations_checked(next:U32,entities:List<&2,Snapshot.Entity>,+fields:List<&2,D.Field>,result:Basic.Decoded>) -> Basic.Decoded: 78 match result: 79 case Basic.Value{values}:resources(next,entities,values,fields,D.field("resources",fields)) 80 case Basic.Failed{error}:Basic.Failed{error} 81 def relation_object(next:U32,entities:List<&2,Snapshot.Entity>,fields:List<&2,D.Field>,raw:D.Raw) -> Basic.Decoded: 82 match raw: 83 case D.Object{values}:relations_checked(next,entities,fields,relations(values)) 84 case other:Basic.invalid(~Graph.Snapshot,"$.relations","object",other) 85 def entities_checked(next:U32,+fields:List<&2,D.Field>,result:Basic.Decoded>) -> Basic.Decoded: 86 match result: 87 case Basic.Value{values}:relation_object(next,values,fields,D.field("relations",fields)) 88 case Basic.Failed{error}:Basic.Failed{error} 89 def entity_array(next:U32,fields:List<&2,D.Field>,raw:D.Raw) -> Basic.Decoded: 90 match raw: 91 case D.Array{values}:entities_checked(next,fields,Basic.entities(values,0)) 92 case other:Basic.invalid(~Graph.Snapshot,"$.entities","array",other) 93 def progress(+fields:List<&2,D.Field>,result:Basic.Decoded) -> Basic.Decoded: 94 match result: 95 case Basic.Value{next}:entity_array(next,fields,D.field("entities",fields)) 96 case Basic.Failed{error}:Basic.Failed{error} 97 def version(+fields:List<&2,D.Field>,+raw:D.Raw,result:Number.Checked) -> Basic.Decoded: 98 match result: 99 case Number.Value{1}:progress(fields,Basic.number("$.nextEntity",D.field("nextEntity",fields),True{})) 100 case _:Basic.Failed{Basic.UnsupportedVersion{raw}} 101 def object(raw:D.Raw) -> Basic.Decoded: 102 match raw: 103 case D.Object{+fields}:version(fields,D.field("version",fields),Number.checked(D.field("version",fields))) 104 case other:Basic.invalid(~Graph.Snapshot,"$","object",other) 105 def finished(original:D.Raw,result:Basic.Decoded) -> Parsed: 106 match result: 107 case Basic.Value{snapshot}:Accepted{snapshot} 108 case Basic.Failed{error}:Rejected{original,error} 109 def parse(+raw:D.Raw) -> Parsed:finished(raw,object(raw)) 110 def saved_keys(values:List<&2,Key.Key>) -> List<&2,D.Raw>: 111 match values: 112 case []:[] 113 case key <> rest:Basic.saved_key(key) <> saved_keys(rest) 114 def saved_groups(values:List<&2,Graph.Group>) -> List<&2,D.Raw>: 115 match values: 116 case []:[] 117 case Graph.Group{target,sources} <> rest:D.Array{[Basic.saved_key(target),D.Array{saved_keys(sources)}]} <> saved_groups(rest) 118 def saved_relations(values:List<&2,Graph.Relation>) -> List<&2,D.Field>: 119 match values: 120 case []:[] 121 case Graph.Relation{name,groups} <> rest:D.Field{name,D.Array{saved_groups(groups)}} <> saved_relations(rest) 122 def encode(value:Graph.Snapshot) -> D.Raw: 123 match value: 124 case Graph.Snapshot{Snapshot.Snapshot{version,next,entities,resources},relations,machines}:D.Object{[D.Field{"version",D.Number{version}},D.Field{"nextEntity",D.Number{next}},D.Field{"entities",D.Array{Basic.saved_entities(entities)}},D.Field{"relations",D.Object{saved_relations(relations)}},D.Field{"resources",D.Object{resources}},D.Field{"machines",D.Object{machines}}]}