aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-11-23 23:56:10 +0000
committerMartin Ashby <martin@ashbysoft.com>2023-11-23 23:56:10 +0000
commita20ce36876487b48dbbd18a38570f4ade522118e (patch)
tree00a1e0c9f5b22fbe3fbd7105de7270bc92d07194
parent3e5a03b51c8debf0b9d41ca477d44f8fb976d65b (diff)
downloadroctorrent-a20ce36876487b48dbbd18a38570f4ade522118e.tar.gz
roctorrent-a20ce36876487b48dbbd18a38570f4ade522118e.tar.bz2
roctorrent-a20ce36876487b48dbbd18a38570f4ade522118e.tar.xz
roctorrent-a20ce36876487b48dbbd18a38570f4ade522118e.zip
Adaptations to allow reading sequential values
-rw-r--r--main.roc116
1 files changed, 89 insertions, 27 deletions
diff --git a/main.roc b/main.roc
index c90531f..a1c3e38 100644
--- a/main.roc
+++ b/main.roc
@@ -4,16 +4,35 @@ app "roctorrent"
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.toU32 ls) is
+ when (Str.toNat ls) is
Ok l ->
- if Num.toU32 (List.len after) == l then
- Ok after
+ if List.len after >= l then
+ Ok (List.split after l)
else
Err Malformatted
Err _err -> Err Malformatted
@@ -39,18 +58,37 @@ expect
res = bDecodeStr (Str.toUtf8 t)
res == Err Malformatted
-bDecodeNum: List U8 -> Result I64 [Malformatted]
+# Decodes an exact number, exta input causes an error
+bDecodeNum: List U8 -> Result I64 [Malformatted Str]
bDecodeNum = \i ->
- when i is
- ['i', .., 'e'] ->
- ii = List.sublist i {start: 1, len: ((List.len i) - 2)}
- when (Str.fromUtf8 ii) is
- Ok iii ->
- when (Str.toI64 iii) is
- Ok res -> Ok res
- Err _err -> Err Malformatted
- Err _err -> Err Malformatted
- _ -> Err Malformatted
+ 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")
@@ -58,19 +96,43 @@ expect
expect
errCases = [
- "",
- "foo",
- "i32",
- "32e",
- "ifooe",
- "ie",
- "i",
- "e",
- "i522222222222222222343423432434322e",
+ {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 \t ->
- res = bDecodeNum (Str.toUtf8 t)
- res == Err Malformatted
+ 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"
+ Stdout.line "Hello, World" \ No newline at end of file