src/hub/hub.bend

ezx@1.4.0.0 · 60 lines · 0 definitions

1# hub/hub: a file fetched from the hub, and checked against the hash that names
2# it. bend accepts any prefix of the sha256, and a package's `0x` name is the
3# first 32 characters of its manifest's digest, so the check is a prefix test.
4import Base
5import ezx@1.4.0.0/src/share/sha.bend as Sha
6
7# The GET is ezhttp's, run by hub/get. What is kept here is the answer's shape: a status on
8# its own first line and then the text, the shape a run answers with and the
9# one curl's answer had, so `R.ok` and `R.text` read it.
10
11# a status other than 200 is a miss with the number in it, never a body
12def get.status(ok: Bool, status: U32, body: String) -> String:
13  match ok:
14    case True{}:
15      "0\n" ++ body
16    case False{}:
17      "22\nthe server answered " ++ U32.show(status)
18
19# a file url read off the disk. curl served these too, and a test that wants a
20# body without a server to serve it is the reason to keep them.
21def get.file.got(got: Maybe<&2, String>, path: String) -> String:
22  match got:
23    case None{}:
24      "2\n" ++ path ++ " is not there"
25    case Some{s}:
26      "0\n" ++ s
27
28# a body is the one that was asked for when its digest starts with the hash
29def matches(want: String, +body: String) -> Bool:
30  String.starts_with(Sha.hex(body), want)
31
32# what a fetch answered: the body when it arrived and hashed right, otherwise
33# the reason, so a caller never mistakes an error page for a package file
34type Got is Data:
35  Miss{why: String}
36  Have{body: String}
37
38# the digest's verdict on a body that did arrive
39def judge.hash(good: Bool, url: String, body: String) -> Got:
40  match good:
41    case True{}:
42      Have{body}
43    case False{}:
44      Miss{url ++ " does not hash to what was asked for"}
45
46# a fetch judged, once the run and the digest are both known
47def judge(ok: Bool, good: Bool, url: String, body: String) -> Got:
48  match ok:
49    case False{}:
50      Miss{url ++ ": " ++ body}
51    case True{}:
52      judge.hash(good, url, body)
53
54# a fetch's outcome on one line
55def show(got: Got) -> String:
56  match got:
57    case Miss{why}:
58      "miss " ++ why
59    case Have{body}:
60      "have " ++ body