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))