This commit is contained in:
parent
97bd0c70d6
commit
d8ffd4a9bd
3 changed files with 50 additions and 2 deletions
|
@ -6,7 +6,8 @@ Based on Noah Pederson's [gleemor] module, licensed under MIT
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This library is licensed under the GNU Affero General Public License version 3, see `LICENSE`.
|
This library is licensed under the GNU Affero General Public License version 3,
|
||||||
|
see `LICENSE`.
|
||||||
|
|
||||||
[Pdor]:https://www.youtube.com/watch?v=k3aehC2SSPw
|
[Pdor]:https://www.youtube.com/watch?v=k3aehC2SSPw
|
||||||
[gleemor]:https://github.com/chiefnoah/gleebor
|
[gleemor]:https://github.com/chiefnoah/gleebor
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub type DecodedValue {
|
||||||
Bytes(value: BitArray)
|
Bytes(value: BitArray)
|
||||||
String(value: String)
|
String(value: String)
|
||||||
Array(List(DecodedValue))
|
Array(List(DecodedValue))
|
||||||
|
Map(List(#(DecodedValue, DecodedValue)))
|
||||||
Null
|
Null
|
||||||
Undefined
|
Undefined
|
||||||
}
|
}
|
||||||
|
@ -47,6 +48,9 @@ pub fn decode(bits: BitArray) -> DecodeResult {
|
||||||
<<4:3, rest:bits>> ->
|
<<4:3, rest:bits>> ->
|
||||||
decode_array(rest)
|
decode_array(rest)
|
||||||
|> map_decoded(Array)
|
|> map_decoded(Array)
|
||||||
|
<<5:3, rest:bits>> ->
|
||||||
|
decode_map(rest)
|
||||||
|
|> map_decoded(Map)
|
||||||
<<7:3, x:5, rest:bits>> if x < 25 -> decode_simple(<<x:5, rest:bits>>)
|
<<7:3, x:5, rest:bits>> if x < 25 -> decode_simple(<<x:5, rest:bits>>)
|
||||||
<<7:3, x:5, rest:bits>> if x >= 25 ->
|
<<7:3, x:5, rest:bits>> if x >= 25 ->
|
||||||
decode_float(<<x:5, rest:bits>>)
|
decode_float(<<x:5, rest:bits>>)
|
||||||
|
@ -93,6 +97,15 @@ fn decode_array(bits: BitArray) -> DecoderResult(List(DecodedValue)) {
|
||||||
decode_next_n([], rest, length)
|
decode_next_n([], rest, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decode_map(
|
||||||
|
bits: BitArray,
|
||||||
|
) -> DecoderResult(List(#(DecodedValue, DecodedValue))) {
|
||||||
|
use #(length, rest) <- try(decode_int(bits))
|
||||||
|
use #(entries, remainder) <- try(decode_next_n([], rest, length * 2))
|
||||||
|
use pairs <- try(into_pairs(entries))
|
||||||
|
Ok(#(pairs, remainder))
|
||||||
|
}
|
||||||
|
|
||||||
fn decode_float(bits: BitArray) -> DecoderResult(IEEEFloat) {
|
fn decode_float(bits: BitArray) -> DecoderResult(IEEEFloat) {
|
||||||
case bits {
|
case bits {
|
||||||
<<25:5, float16:bytes-size(2), rest:bits>> ->
|
<<25:5, float16:bytes-size(2), rest:bits>> ->
|
||||||
|
@ -115,6 +128,21 @@ fn decode_simple(bits: BitArray) -> DecodeResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_pairs(list: List(a)) -> Result(List(#(a, a)), DecodeError) {
|
||||||
|
into_pairs_aggr([], list)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_pairs_aggr(
|
||||||
|
accum: List(#(a, a)),
|
||||||
|
remaining: List(a),
|
||||||
|
) -> Result(List(#(a, a)), DecodeError) {
|
||||||
|
case remaining {
|
||||||
|
[] -> Ok(reverse(accum))
|
||||||
|
[_] -> Error(Malformed)
|
||||||
|
[key, value, ..rest] -> into_pairs_aggr([#(key, value), ..accum], rest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn decode_next_n(
|
fn decode_next_n(
|
||||||
retrieved: List(DecodedValue),
|
retrieved: List(DecodedValue),
|
||||||
rest: BitArray,
|
rest: BitArray,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import gleeunit/should
|
||||||
import ieee_float.{finite, nan, positive_infinity}
|
import ieee_float.{finite, nan, positive_infinity}
|
||||||
import kmer.{
|
import kmer.{
|
||||||
type DecodeResult, type DecodedValue, Array, Boolean, Bytes, Float, Integer,
|
type DecodeResult, type DecodedValue, Array, Boolean, Bytes, Float, Integer,
|
||||||
Null, String, Undefined,
|
Map, Null, String, Undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -136,6 +136,25 @@ pub fn decode_list_test() {
|
||||||
|> table_fn(table_test_decode)
|
|> table_fn(table_test_decode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn decode_map_test() {
|
||||||
|
[
|
||||||
|
#(
|
||||||
|
<<5:3, 2:5, 3:3, 8:5, "test-key", 5, 3:3, 5:5, "other", 10>>,
|
||||||
|
Map([#(String("test-key"), Integer(5)), #(String("other"), Integer(10))]),
|
||||||
|
),
|
||||||
|
#(
|
||||||
|
<<5:3, 24:5, 4:8, 1, 2, 3, 4, 5, 6, 7, 8>>,
|
||||||
|
Map([
|
||||||
|
#(Integer(1), Integer(2)),
|
||||||
|
#(Integer(3), Integer(4)),
|
||||||
|
#(Integer(5), Integer(6)),
|
||||||
|
#(Integer(7), Integer(8)),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|> table_fn(table_test_decode)
|
||||||
|
}
|
||||||
|
|
||||||
fn table_fn(tests: List(#(a, b)), test_fn: fn(a, b) -> Nil) {
|
fn table_fn(tests: List(#(a, b)), test_fn: fn(a, b) -> Nil) {
|
||||||
list.map(tests, fn(t) {
|
list.map(tests, fn(t) {
|
||||||
let #(test_case, expected) = t
|
let #(test_case, expected) = t
|
||||||
|
|
Loading…
Reference in a new issue