From 7f1f2b46ba140d25ffed4832c3fec52585f4a9bc Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Fri, 24 Nov 2023 20:04:26 +0000 Subject: Add list decoding --- main.roc | 130 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 28 deletions(-) diff --git a/main.roc b/main.roc index a1c3e38..3d48fcd 100644 --- a/main.roc +++ b/main.roc @@ -4,13 +4,6 @@ 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 -> @@ -110,29 +103,110 @@ expect 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 +# Tags for storing heterogenous collections +BVal: [ + BStr (List U8), + BNum I64, + BList (List BVal), +] + +# Detects and decodes any kind of element. +bDecodeValueAndRem: (List U8) -> Result {res: BVal, others: (List U8)} [Malformatted, End (List U8)] +bDecodeValueAndRem = \i -> + when (List.first i) is + Ok first -> + when first is + '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' -> + when bDecodeStrAndRemainder i is + Ok {before, others} -> + Ok {res: BStr before, others: others} + Err _err -> + Err Malformatted + 'i' -> + when bDecodeNumAndRem i is + Ok {num, rem} -> + Ok {res: BNum num, others: rem} + Err _err -> + Err Malformatted + 'l' -> + when bDecodeListAndRem i is + Ok {res, others} -> + Ok {res: BList res, others: others} + Err _err -> + Err Malformatted + 'e' -> + {before, others} = List.split i 1 + Err (End others) + _ -> + Err Malformatted + Err _err -> Err Malformatted + +expect + res = bDecodeValueAndRem (Str.toUtf8 "i64efoo") + res == Ok {res: BNum 64, others: (Str.toUtf8 "foo")} + +expect + res = bDecodeValueAndRem (Str.toUtf8 "3:foo3:foo") + res == Ok {res: BStr (Str.toUtf8 "foo"), others: (Str.toUtf8 "3:foo")} + +expect + res = bDecodeValueAndRem (Str.toUtf8 "efoo") + res == Err (End (Str.toUtf8 "foo")) expect - res = bDecodeList (Str.toUtf8 "li64e3:fooe") - res == Ok [BNum 64, BStr "foo"] + res = bDecodeValueAndRem (Str.toUtf8 "z") + res == Err Malformatted + +# Decodes a list. List elements can be any +bDecodeList: (List U8) -> Result {res: (List BVal)} [Malformatted] +bDecodeList = \i -> + when bDecodeListAndRem i is + Ok {res, others} -> + if (List.len others) == 0 then + Ok {res: res} + else + Err Malformatted + Err e -> + Err e + +bDecodeListAndRem: (List U8) -> Result {res: (List BVal), others: (List U8)} [Malformatted] +bDecodeListAndRem = \i -> + when List.first i is + Ok f -> + if f == 'l' then + {before, others} = List.split i 1 + bDecodeListAndRemInternal [] others + else + Err Malformatted + Err _e -> Err Malformatted + +bDecodeListAndRemInternal: List BVal, List U8 -> Result {res: (List BVal), others: (List U8)} [Malformatted] +bDecodeListAndRemInternal = \l, i -> + when bDecodeValueAndRem i is + Ok {res, others} -> + l2 = List.append l res + bDecodeListAndRemInternal l2 others + Err e -> when e is + End others -> + Ok {res: l, others: others} + Malformatted -> + Err Malformatted + +expect + res = bDecodeList (Str.toUtf8 "le") + res == Ok { res: []} + +expect + res = bDecodeList (Str.toUtf8 "li123e3:fooe") + res == Ok { res: [BNum 123i64, BStr (Str.toUtf8 "foo")] } + +expect + res = bDecodeList (Str.toUtf8 "li123e3:fooe123") + res == Err Malformatted + +expect + res = bDecodeList (Str.toUtf8 "lli123eee") + res == Ok { res: [BList [BNum 123i64]]} main = Stdout.line "Hello, World" \ No newline at end of file -- cgit v1.2.3-ZIG