Skip to content

Commit

Permalink
Merge pull request #1 from adomurad/v0.2.0
Browse files Browse the repository at this point in the history
V0.2.0
  • Loading branch information
adomurad authored Jul 11, 2024
2 parents 086e537 + e5c9000 commit 774ff0b
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 315 deletions.
7 changes: 7 additions & 0 deletions package/Base64.roc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ expect
actual = decodeStr input
actual == expected

expect
# 10 and 13 are line feed and carriage return
input = [100, 71, 10, 86, 13, 122, 100, 10, 13, 65, 61, 61]
expected = "test" |> Str.toUtf8
actual = decodeUtf8 input
actual == expected

expect
input = "Pz8/"
expected = "???" |> Str.toUtf8 |> Ok
Expand Down
7 changes: 7 additions & 0 deletions package/Base64Url.roc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ expect
actual = decodeStr input
actual == expected

expect
# 10 and 13 are line feed and carriage return
input = [100, 71, 10, 86, 13, 122, 100, 10, 13, 65, 61, 61]
expected = "test" |> Str.toUtf8
actual = decodeUtf8 input
actual == expected

expect
input = "Pz8_"
expected = "???" |> Str.toUtf8 |> Ok
Expand Down
50 changes: 32 additions & 18 deletions package/Internal/DecodeCore.roc
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,7 @@ decode = \bytes, decodeChar ->
# calc final padding chars
paddingLen = calculatePadding list

chunks = list |> List.chunksOf 4
decodedList =
chunks
|> List.walk [] \state, element ->
when element is
[a, b, c, d] ->
b1 = (0u32 |> Num.shiftLeftBy 6) + (decodeChar a)
b2 = (b1 |> Num.shiftLeftBy 6) + (decodeChar b)
b3 = (b2 |> Num.shiftLeftBy 6) + (decodeChar c)
b4 = (b3 |> Num.shiftLeftBy 6) + (decodeChar d)

c1 = b4 |> Num.shiftRightBy 16 |> Num.bitwiseAnd 0xff |> Num.toU8
c2 = b4 |> Num.shiftRightBy 8 |> Num.bitwiseAnd 0xff |> Num.toU8
c3 = b4 |> Num.shiftRightBy 0 |> Num.bitwiseAnd 0xff |> Num.toU8

List.concat state [c1, c2, c3]

_ -> crash "Base64.decode: this error should not be possible"
decodedList = decodeList list [] decodeChar

decodedList |> List.dropLast paddingLen

Expand All @@ -45,3 +28,34 @@ calculatePadding = \bytes ->
[61, 61] -> 2
[_, 61] -> 1
_ -> 0

#

decodeList = \list, state, decodeChar ->
when list is
# 10 - line feed must be ignored
[a, b, c, 10, .. as rest] -> decodeList (List.concat [a, b, c] rest) state decodeChar
[a, b, 10, .. as rest] -> decodeList (List.concat [a, b] rest) state decodeChar
[a, 10, .. as rest] -> decodeList (List.prepend rest a) state decodeChar
[10, .. as rest] -> decodeList rest state decodeChar
# 13 - carriage return must be ignored
[a, b, c, 13, .. as rest] -> decodeList (List.concat [a, b, c] rest) state decodeChar
[a, b, 13, .. as rest] -> decodeList (List.concat [a, b] rest) state decodeChar
[a, 13, .. as rest] -> decodeList (List.prepend rest a) state decodeChar
[13, .. as rest] -> decodeList rest state decodeChar
#
[a, b, c, d, .. as rest] ->
b1 = (0u32 |> Num.shiftLeftBy 6) + (decodeChar a)
b2 = (b1 |> Num.shiftLeftBy 6) + (decodeChar b)
b3 = (b2 |> Num.shiftLeftBy 6) + (decodeChar c)
b4 = (b3 |> Num.shiftLeftBy 6) + (decodeChar d)

c1 = b4 |> Num.shiftRightBy 16 |> Num.bitwiseAnd 0xff |> Num.toU8
c2 = b4 |> Num.shiftRightBy 8 |> Num.bitwiseAnd 0xff |> Num.toU8
c3 = b4 |> Num.shiftRightBy 0 |> Num.bitwiseAnd 0xff |> Num.toU8

next = List.concat state [c1, c2, c3]
decodeList rest next decodeChar

[] -> state
_ -> crash "Base64.decode: this error should not be possible"
85 changes: 44 additions & 41 deletions package/Internal/EncodeCore.roc
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,61 @@ module [

encode : List U8, (U32 -> U8) -> List U8
encode = \bytes, encodeChar ->
chunks = bytes |> List.chunksOf 3
encodeHelper bytes [] encodeChar

chunks
|> List.walk [] \state, chunk ->
when chunk is
[a, b, c] ->
b1 = a |> Num.toU32
b2 = b |> Num.toU32
b3 = c |> Num.toU32
encodeHelper = \list, state, encodeChar ->
when list is
[a, b, c, .. as rest] ->
b1 = a |> Num.toU32
b2 = b |> Num.toU32
b3 = c |> Num.toU32

# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3
# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3

# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = bits |> Num.shiftRightBy 6 |> Num.bitwiseAnd 0x3f |> encodeChar
c4 = bits |> Num.bitwiseAnd 0x3f |> encodeChar
# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = bits |> Num.shiftRightBy 6 |> Num.bitwiseAnd 0x3f |> encodeChar
c4 = bits |> Num.bitwiseAnd 0x3f |> encodeChar

state |> List.concat [c1, c2, c3, c4]
next = state |> List.concat [c1, c2, c3, c4]
encodeHelper rest next encodeChar

[a, b] ->
b1 = a |> Num.toU32
b2 = b |> Num.toU32
b3 = 0u32
[a, b] ->
b1 = a |> Num.toU32
b2 = b |> Num.toU32
b3 = 0u32

# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3
# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3

# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = bits |> Num.shiftRightBy 6 |> Num.bitwiseAnd 0x3f |> encodeChar
c4 = '='
# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = bits |> Num.shiftRightBy 6 |> Num.bitwiseAnd 0x3f |> encodeChar
c4 = '='

state |> List.concat [c1, c2, c3, c4]
next = state |> List.concat [c1, c2, c3, c4]
encodeHelper [] next encodeChar

[a] ->
b1 = a |> Num.toU32
b2 = 0u32
b3 = 0u32
[a] ->
b1 = a |> Num.toU32
b2 = 0u32
b3 = 0u32

# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3
# create a 24-bit number from the next 3 bytes
bits = (b1 |> Num.shiftLeftBy 16) |> Num.bitwiseOr (b2 |> Num.shiftLeftBy 8) |> Num.bitwiseOr b3

# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = '='
c4 = '='
# extract four 6-bit groups
c1 = bits |> Num.shiftRightBy 18 |> Num.bitwiseAnd 0x3f |> encodeChar
c2 = bits |> Num.shiftRightBy 12 |> Num.bitwiseAnd 0x3f |> encodeChar
c3 = '='
c4 = '='

state |> List.concat [c1, c2, c3, c4]
next = state |> List.concat [c1, c2, c3, c4]
encodeHelper [] next encodeChar

_ -> crash "Base64.encode: this error should not be possible"
[] -> state
_ -> crash "Base64.encode: this error should not be possible"

127 changes: 0 additions & 127 deletions temp/decode.roc

This file was deleted.

Loading

0 comments on commit 774ff0b

Please sign in to comment.