From a20ce36876487b48dbbd18a38570f4ade522118e Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Thu, 23 Nov 2023 23:56:10 +0000 Subject: Adaptations to allow reading sequential values --- main.roc | 116 ++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file 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 -- cgit v1.2.3-ZIG