src/body.bend

emerging-ezhttp@0.20.0.0 · 68 lines · 0 definitions

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).
5import Base
6import bend-kit-bytes@0.3.2.0/bytes.bend as Bytes
7
8# what rides in a request: nothing, text, or raw octets
9type 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)
16type 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
21def 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
27def 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
37def 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
45def body.empty() -> Body:
46  Empty{}
47
48# UTF-8 text body
49def body.text(s: String) -> Body:
50  Plain{s}
51
52# octets body
53def 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)
58def 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
62def 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
66def body.decode(~A: Data, ~from_text: String -> Maybe<&2, A>, s: String)
67  -> Maybe<&2, A>:
68  from_text(s)