1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
app "roctorrent"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" }
imports [pf.Stdout]
provides [main] to pf
BVal: [
BStr Str,
BNum I64,
BList (List BVal),
# TODO add dict!
]
# Decodes an exact string, errors if there is remaining unused data
bDecodeStr: List U8 -> Result (List U8) [Malformatted]
bDecodeStr = \i ->
when bDecodeStrAndRemainder i is
Ok {before, others} ->
if List.len others == 0 then
Ok before
else
Err Malformatted
Err _ -> Err Malformatted
# Decodes a string and returns the remainder of the input as well if there was any
bDecodeStrAndRemainder: List U8 -> Result {before: List U8, others: List U8} [Malformatted]
bDecodeStrAndRemainder = \i ->
when (List.splitFirst i ':') is
Ok {before, after} ->
when (Str.fromUtf8 before) is
Ok ls ->
when (Str.toNat ls) is
Ok l ->
if List.len after >= l then
Ok (List.split after l)
else
Err Malformatted
Err _err -> Err Malformatted
Err _err -> Err Malformatted
Err _err -> Err Malformatted
expect
res = bDecodeStr (Str.toUtf8 "3:foo")
res == Ok (Str.toUtf8 "foo")
expect
errCases = [
"",
"foo",
"1:foo",
"4:foo",
":",
"foo:",
"1:",
"::",
]
List.all errCases \t ->
res = bDecodeStr (Str.toUtf8 t)
res == Err Malformatted
# Decodes an exact number, exta input causes an error
bDecodeNum: List U8 -> Result I64 [Malformatted Str]
bDecodeNum = \i ->
when bDecodeNumAndRem i is
Ok {num, rem} ->
if (List.len rem) == 0 then
Ok num
else
Err (Malformatted "remaining characters after number")
Err e -> Err e
# Decodes a number and returns the number and any unused input
bDecodeNumAndRem: List U8 -> Result {num: I64, rem: (List U8)} [Malformatted Str]
bDecodeNumAndRem = \i ->
when (List.first i) is
Ok f ->
if f == 'i' then
when List.findFirstIndex i (\j -> j == 'e') is
Ok ix ->
{before, others} = List.split i (ix+1)
numl = List.sublist before {start: 1, len: ix-1}
when (Str.fromUtf8 numl) is
Ok nums ->
when (Str.toI64 nums) is
Ok num -> Ok {num: num, rem: others}
Err _e -> Err (Malformatted "failed to parse number from \(nums)")
Err _e -> Err (Malformatted "failed to parse utf8")
Err _e -> Err (Malformatted "failed to find number end char 'e'")
else
Err (Malformatted "number didn't start with 'i'")
Err _e -> Err (Malformatted "number string was empty")
expect
res = bDecodeNum (Str.toUtf8 "i32e")
res == Ok 32i64
expect
errCases = [
{case: "", msg: "number string was empty"},
{case: "foo", msg: "number didn't start with 'i'"},
{case: "i32", msg: "failed to find number end char 'e'"},
{case: "32e", msg: "number didn't start with 'i'"},
{case: "ifooe", msg: "failed to parse number from foo"},
{case: "ie", msg: "failed to parse number from "},
{case: "i", msg: "failed to find number end char 'e'"},
{case: "e", msg: "number didn't start with 'i'"},
{case: "i522222222222222222343423432434322e", msg: "failed to parse number from 522222222222222222343423432434322"},
]
List.all errCases \{case, msg} ->
res = bDecodeNum (Str.toUtf8 case)
res == Err (Malformatted msg)
bDecodeList: (List U8) -> Result (List BVal) [Malformatted]
bDecodeList = \_i ->
Ok [BNum 64, BStr "foo"]
#when i is
# ['l', .., 'e'] ->
# _ -> Err Malformatted
#bDecodeListInner: (List U8, List BVal) -> Result {res: (List BVal), others: (List U8)} [Malformatted]
#bDecodeListInner = \i, o ->
# when (List.first i) is
# Ok first ->
# when first is
# '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' ->
# when bDecodeStringAndRemainder first is
# Ok {before, others} ->
# Err _err -> Err Malformatted
# 'i' ->
# bDecode
# Err _err -> Err Malformatted
expect
res = bDecodeList (Str.toUtf8 "li64e3:fooe")
res == Ok [BNum 64, BStr "foo"]
main =
Stdout.line "Hello, World"
|