mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-23 22:45:14 +00:00
134 lines
3.5 KiB
Text
134 lines
3.5 KiB
Text
interface Bytes.Encode exposes [ByteEncoder, sequence, u8, u16, bytes, empty, encode] imports []
|
|
|
|
Endianness : [BE, LE]
|
|
|
|
ByteEncoder : [Signed8 I8, Unsigned8 U8, Signed16 Endianness I16, Unsigned16 Endianness U16, Sequence Nat (List ByteEncoder), Bytes (List U8)]
|
|
|
|
u8 : U8 -> ByteEncoder
|
|
u8 = \value -> Unsigned8 value
|
|
|
|
empty : ByteEncoder
|
|
empty =
|
|
foo : List ByteEncoder
|
|
foo = []
|
|
|
|
Sequence 0 foo
|
|
|
|
u16 : Endianness, U16 -> ByteEncoder
|
|
u16 = \endianness, value -> Unsigned16 endianness value
|
|
|
|
bytes : List U8 -> ByteEncoder
|
|
bytes = \bs -> Bytes bs
|
|
|
|
sequence : List ByteEncoder -> ByteEncoder
|
|
sequence = \encoders ->
|
|
Sequence (getWidths encoders 0) encoders
|
|
|
|
getWidth : ByteEncoder -> Nat
|
|
getWidth = \encoder ->
|
|
when encoder is
|
|
Signed8 _ -> 1
|
|
Unsigned8 _ -> 1
|
|
Signed16 _ _ -> 2
|
|
Unsigned16 _ _ -> 2
|
|
# Signed32 _ -> 4
|
|
# Unsigned32 _ -> 4
|
|
# Signed64 _ -> 8
|
|
# Unsigned64 _ -> 8
|
|
# Signed128 _ -> 16
|
|
# Unsigned128 _ -> 16
|
|
Sequence w _ -> w
|
|
Bytes bs -> List.len bs
|
|
|
|
getWidths : List ByteEncoder, Nat -> Nat
|
|
getWidths = \encoders, initial ->
|
|
List.walk encoders initial \accum, encoder -> accum + getWidth encoder
|
|
|
|
encode : ByteEncoder -> List U8
|
|
encode = \encoder ->
|
|
output = List.repeat 0 (getWidth encoder)
|
|
|
|
encodeHelp encoder 0 output
|
|
|> .output
|
|
|
|
encodeHelp : ByteEncoder, Nat, List U8 -> { output : List U8, offset : Nat }
|
|
encodeHelp = \encoder, offset, output ->
|
|
when encoder is
|
|
Unsigned8 value ->
|
|
{
|
|
output: List.set output offset value,
|
|
offset: offset + 1,
|
|
}
|
|
|
|
Signed8 value ->
|
|
cast : U8
|
|
cast = Num.intCast value
|
|
|
|
{
|
|
output: List.set output offset cast,
|
|
offset: offset + 1,
|
|
}
|
|
|
|
Unsigned16 endianness value ->
|
|
a : U8
|
|
a = Num.intCast (Num.shiftRightBy value 8)
|
|
|
|
b : U8
|
|
b = Num.intCast value
|
|
|
|
newOutput =
|
|
when endianness is
|
|
BE ->
|
|
output
|
|
|> List.set (offset + 0) a
|
|
|> List.set (offset + 1) b
|
|
|
|
LE ->
|
|
output
|
|
|> List.set (offset + 0) b
|
|
|> List.set (offset + 1) a
|
|
|
|
{
|
|
output: newOutput,
|
|
offset: offset + 2,
|
|
}
|
|
|
|
Signed16 endianness value ->
|
|
a : U8
|
|
a = Num.intCast (Num.shiftRightBy value 8)
|
|
|
|
b : U8
|
|
b = Num.intCast value
|
|
|
|
newOutput =
|
|
when endianness is
|
|
BE ->
|
|
output
|
|
|> List.set (offset + 0) a
|
|
|> List.set (offset + 1) b
|
|
|
|
LE ->
|
|
output
|
|
|> List.set (offset + 0) b
|
|
|> List.set (offset + 1) a
|
|
|
|
{
|
|
output: newOutput,
|
|
offset: offset + 1,
|
|
}
|
|
|
|
Bytes bs ->
|
|
List.walk
|
|
bs
|
|
{ output, offset }
|
|
\accum, byte -> {
|
|
offset: accum.offset + 1,
|
|
output: List.set accum.output offset byte,
|
|
}
|
|
|
|
Sequence _ encoders ->
|
|
List.walk
|
|
encoders
|
|
{ output, offset }
|
|
\accum, single ->
|
|
encodeHelp single accum.offset accum.output
|