1 import Base 2 import ./ordinary_declaration.bend as C 3 import ./persistence_declaration.bend as Decl 4 import ./decode_data.bend as D 5 import ./decode.bend as Decode 6 7 type Leaf<-S:Data,-P:Type,-identity:C.Declaration,-project:P -> P & D.Raw> is Type: 8 Plain{} 9 Transient{} 10 Constructed{declaration:Decl.Constructed} 11 type Refusal is Data: 12 PlainUnserializable{key:String} 13 InvalidProjection{key:String,error:D.Error} 14 MalformedColumn{key:String} 15 DescriptorMismatch{expected:String,actual:String} 16 type Field is Data: 17 Omitted{} 18 Saved{field:D.Field} 19 Refused{reason:Refusal} 20 21 def plain(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,declaration:Decl.Plain) -> Leaf:Plain{} 22 def transient(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,declaration:Decl.Transient) -> Leaf:Transient{} 23 def constructed(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,declaration:Decl.Constructed) -> Leaf:Constructed{declaration} 24 def eligibility(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,recipe:Leaf) -> Leaf & Maybe<&2,Refusal>: 25 match recipe: 26 case Plain{}:(Plain{},Some{PlainUnserializable{C.key(~S,~P,identity)}}) 27 case Transient{}:(Transient{},None{}) 28 case Constructed{declaration}:(Constructed{declaration},None{}) 29 def projected(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,declaration:Decl.Constructed,result:D.Receipt

) -> Leaf & (P & Field): 30 match result: 31 case D.Receipt{owner,D.Accepted{value}}:(Constructed{declaration},(owner,Saved{D.Field{C.key(~S,~P,identity),value}})) 32 case D.Receipt{owner,D.Rejected{error}}:(Constructed{declaration},(owner,Refused{InvalidProjection{C.key(~S,~P,identity),error}})) 33 # The same retained ordinary declaration supplies codec and actual-owner 34 # projection. Transient and Plain never evaluate the projection. 35 def export(~S:Data,~P:Type,~identity:C.Declaration,~project:P -> P & D.Raw,recipe:Leaf,owner:P) -> Leaf & (P & Field): 36 match recipe: 37 case Plain{}:(Plain{},(owner,Refused{PlainUnserializable{C.key(~S,~P,identity)}})) 38 case Transient{}:(Transient{},(owner,Omitted{})) 39 case Constructed{+declaration}:projected(~S,~P,~identity,~project,declaration,Decode.decode_owner(~P,~project,Decl.codec(~S,~P,~identity,~project,declaration),owner))