1 # ezhttp/src/body: request entity as empty, UTF-8 text, or packed octets 2 # (bend-kit-bytes). Core does not depend on ezjson. Callers plug 3 # encode/decode through Bend type parameters (BYO JSON or any other 4 # representation). 5 import Base 6 import bend-kit-bytes@0.3.2.0/bytes.bend as Bytes 7 8 # what rides in a request: nothing, text, or raw octets 9 type Body is Type: 10 Empty{} 11 Plain{text: String} 12 Octets{bytes: Bytes.Bytes} 13 14 # what the request text needs to know of a body: its text, or how many 15 # octets follow it (SPEC.md HTTP-CLI-10) 16 type Shape is Data: 17 ShapeText{text: String} 18 ShapeOctets{n: U32} 19 20 # an octets body's count: its shape, and the octets handed back 21 def body.sized(r: Bytes.Bytes & U32) -> Shape & Bytes.Bytes: 22 (b, +n) = r 23 (ShapeOctets{n}, b) 24 25 # a body as its shape and the octets sent after the request text: a text 26 # body's are none, and the empty body is the empty text 27 def body.shape(b: Body) -> Shape & Bytes.Bytes: 28 match b: 29 case Empty{}: 30 (ShapeText{""}, Bytes.new(0)) 31 case Plain{text}: 32 (ShapeText{text}, Bytes.new(0)) 33 case Octets{bytes}: 34 body.sized(Bytes.length(bytes)) 35 36 # octets, one character each (each 0..255), from a list of their values 37 def octets.chars(bs: List<&2, U32>) -> String: 38 match bs: 39 case []: 40 "" 41 case h <> t: 42 SCon{Char.from_u32(h), octets.chars(t)} 43 44 # empty body 45 def body.empty() -> Body: 46 Empty{} 47 48 # UTF-8 text body 49 def body.text(s: String) -> Body: 50 Plain{s} 51 52 # octets body 53 def body.octets(bytes: Bytes.Bytes) -> Body: 54 Octets{bytes} 55 56 # an octets body from a list of octet values (each 0..255; a value past 255 57 # keeps its low 8 bits) 58 def body.list(bs: List<&2, U32>) -> Body: 59 Octets{Bytes.from_string(octets.chars(bs))} 60 61 # BYO encode: any value to a text body via the caller's encoder 62 def body.encode(~A: Data, ~to_text: A -> String, value: A) -> Body: 63 Plain{to_text(value)} 64 65 # BYO decode: body text to a value via the caller's decoder 66 def body.decode(~A: Data, ~from_text: String -> Maybe<&2, A>, s: String) 67 -> Maybe<&2, A>: 68 from_text(s)