Merge pull request 'Throw on unmatched value and add documentation' (#3) from throw_on_unmatched into main
Reviewed-on: #3
This commit is contained in:
commit
85019edf46
12
README.md
12
README.md
@ -7,13 +7,21 @@ See the [SSB Binary Field Encodings Specification](https://github.com/ssbc/ssb-b
|
||||
## Encoding
|
||||
|
||||
```elixir
|
||||
SsbBfe.encode(value)
|
||||
SsbBfe.encode("@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519")
|
||||
<<0, 0, 28, 74, 178, 247, 141, 19, 234, 224, 126, 79, 231, 125, 37, 166, 185,
|
||||
241, 163, 95, 71, 50, 241, 245, 228, 86, 170, 70, 101, 140, 25, 167, 146,
|
||||
105>>
|
||||
```
|
||||
|
||||
## Decoding
|
||||
|
||||
```elixir
|
||||
SsbBfe.decode(value)
|
||||
SsbBfe.decode(
|
||||
<<0, 0, 28, 74, 178, 247, 141, 19, 234, 224, 126, 79, 231, 125, 37, 166, 185,
|
||||
241, 163, 95, 71, 50, 241, 245, 228, 86, 170, 70, 101, 140, 25, 167, 146,
|
||||
105>>
|
||||
)
|
||||
"@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519"
|
||||
```
|
||||
|
||||
## Supported Types
|
||||
|
@ -1,20 +1,22 @@
|
||||
defmodule SsbBfe do
|
||||
@moduledoc """
|
||||
Documentation for `SsbBfe`.
|
||||
"""
|
||||
Binary Field Encodings (BFE) for Secure Scuttlebutt (SSB).
|
||||
|
||||
@doc """
|
||||
Hello world.
|
||||
Encode and decode TFD values.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> SsbBfe.hello()
|
||||
:world
|
||||
iex> SsbBfe.encode("@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519")
|
||||
<<0, 0, 28, 74, 178, 247, 141, 19, 234, 224, 126, 79, 231, 125, 37, 166, 185,
|
||||
241, 163, 95, 71, 50, 241, 245, 228, 86, 170, 70, 101, 140, 25, 167, 146,
|
||||
105>>
|
||||
|
||||
...> SsbBfe.decode(<<0, 0, 28, 74, 178, 247, 141, 19, 234, 224, 126, 79, 231, 125, 37, 166, 185,
|
||||
241, 163, 95, 71, 50, 241, 245, 228, 86, 170, 70, 101, 140, 25, 167, 146,
|
||||
105>>)
|
||||
"@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519"
|
||||
|
||||
"""
|
||||
def hello do
|
||||
:world
|
||||
end
|
||||
|
||||
# ENCODE
|
||||
|
||||
@ -33,8 +35,8 @@ defmodule SsbBfe do
|
||||
end
|
||||
|
||||
def encode(value) when is_tuple(value) do
|
||||
Enum.map(Tuple.to_list(value), fn x -> encode(x) end) |>
|
||||
List.to_tuple()
|
||||
Enum.map(Tuple.to_list(value), fn x -> encode(x) end)
|
||||
|> List.to_tuple()
|
||||
end
|
||||
|
||||
def encode(value) when is_bitstring(value) do
|
||||
@ -89,8 +91,8 @@ defmodule SsbBfe do
|
||||
6 == first_byte ->
|
||||
SsbBfe.Decoder.decode_generic(value)
|
||||
|
||||
nil ->
|
||||
true
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -111,7 +113,7 @@ defmodule SsbBfe do
|
||||
end
|
||||
|
||||
def decode(value) when is_tuple(value) do
|
||||
Enum.map(Tuple.to_list(value), fn x -> decode(x) end) |>
|
||||
List.to_tuple()
|
||||
Enum.map(Tuple.to_list(value), fn x -> decode(x) end)
|
||||
|> List.to_tuple()
|
||||
end
|
||||
end
|
||||
|
@ -1,42 +1,56 @@
|
||||
defmodule SsbBfe.Decoder do
|
||||
# Split the TF tag from the data bytes and base64 encode them.
|
||||
defp extract_base64_data(bin, tf_tag) do
|
||||
[_, base64_data] = :binary.split(bin, tf_tag)
|
||||
Base.encode64(base64_data)
|
||||
end
|
||||
|
||||
def decode_blob(blob) do
|
||||
encoded_base64_data = extract_base64_data(blob, <<2, 0>>)
|
||||
@doc """
|
||||
Take a blob ID as an encoded binary and return the dedoded string representing the TFD.
|
||||
"""
|
||||
def decode_blob(blob_id) do
|
||||
encoded_base64_data = extract_base64_data(blob_id, <<2, 0>>)
|
||||
"&" <> encoded_base64_data <> ".sha256"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take an encrypted box as an encoded binary and return the decoded string representind the TFD.
|
||||
|
||||
`decode_box/1` calls the appropriate `decode_box/2` clause based on the value of the TF tag extracted from the encoded box.
|
||||
"""
|
||||
def decode_box(box) do
|
||||
tf_tag = binary_part(box, 0, 2)
|
||||
decode_box(box, tf_tag)
|
||||
end
|
||||
|
||||
# Matches box.
|
||||
def decode_box(box, <<5, 0>>) do
|
||||
encoded_base64_data = extract_base64_data(box, <<5, 0>>)
|
||||
encoded_base64_data <> ".box"
|
||||
end
|
||||
|
||||
# Matches box2.
|
||||
def decode_box(box, <<5, 1>>) do
|
||||
encoded_base64_data = extract_base64_data(box, <<5, 1>>)
|
||||
encoded_base64_data <> ".box2"
|
||||
end
|
||||
|
||||
def decode_feed(feed) do
|
||||
tf_tag = binary_part(feed, 0, 2)
|
||||
decode_feed(feed, tf_tag)
|
||||
@doc """
|
||||
Take a feed ID as an encoded binary and return the decoded string representing the TFD.
|
||||
|
||||
`decode_feed/1` calls the appropriate `decode_feed/2` clause based on the value of the TF tag extracted from the encoded feed.
|
||||
"""
|
||||
def decode_feed(feed_id) do
|
||||
tf_tag = binary_part(feed_id, 0, 2)
|
||||
decode_feed(feed_id, tf_tag)
|
||||
end
|
||||
|
||||
# Matches classic feed.
|
||||
def decode_feed(feed, <<0, 0>>) do
|
||||
encoded_base64_data = extract_base64_data(feed, <<0, 0>>)
|
||||
def decode_feed(feed_id, <<0, 0>>) do
|
||||
encoded_base64_data = extract_base64_data(feed_id, <<0, 0>>)
|
||||
"@" <> encoded_base64_data <> ".ed25519"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take an encoded generic value as an encoded binary and return `true`, `false`, `nil`, plain bytes or a decoded string.
|
||||
"""
|
||||
def decode_generic(<<6, 1, 1>>), do: true
|
||||
|
||||
def decode_generic(<<6, 1, 0>>), do: false
|
||||
@ -48,28 +62,36 @@ defmodule SsbBfe.Decoder do
|
||||
decode_generic(generic, tf_tag)
|
||||
end
|
||||
|
||||
# Matches generic string.
|
||||
def decode_generic(str, <<6, 0>>) do
|
||||
[_, str_data] = :binary.split(str, <<6, 0>>)
|
||||
str_data
|
||||
end
|
||||
|
||||
# Matches generic bytes.
|
||||
def decode_generic(bytes, <<6, 3>>), do: bytes
|
||||
|
||||
def decode_msg(msg) do
|
||||
tf_tag = binary_part(msg, 0, 2)
|
||||
decode_msg(msg, tf_tag)
|
||||
def decode_generic(bytes, <<6, 3>>) do
|
||||
[_, bytes] = :binary.split(bytes, <<6, 3>>)
|
||||
bytes
|
||||
end
|
||||
|
||||
# Matches classic message.
|
||||
def decode_msg(msg, <<1, 0>>) do
|
||||
encoded_base64_data = extract_base64_data(msg, <<1, 0>>)
|
||||
@doc """
|
||||
Take a message ID as an encoded binary and return the decoded string representing the TFD.
|
||||
|
||||
`decode_msg/1` calls the appropriate `decode_msg/2` clause based on the value of the TF tag extracted from the encoded message.
|
||||
"""
|
||||
def decode_msg(msg_id) do
|
||||
tf_tag = binary_part(msg_id, 0, 2)
|
||||
decode_msg(msg_id, tf_tag)
|
||||
end
|
||||
|
||||
def decode_msg(msg_id, <<1, 0>>) do
|
||||
encoded_base64_data = extract_base64_data(msg_id, <<1, 0>>)
|
||||
"%" <> encoded_base64_data <> ".sha256"
|
||||
end
|
||||
|
||||
def decode_sig(sig) do
|
||||
encoded_base64_data = extract_base64_data(sig, <<4, 0>>)
|
||||
@doc """
|
||||
Take a signature ID as an encoded binary, extract and encode the base64 data and return the dedoded string representing the TFD.
|
||||
"""
|
||||
def decode_sig(sig_id) do
|
||||
encoded_base64_data = extract_base64_data(sig_id, <<4, 0>>)
|
||||
encoded_base64_data <> ".sig.ed25519"
|
||||
end
|
||||
end
|
||||
|
@ -11,42 +11,65 @@ defmodule SsbBfe.Encoder do
|
||||
Base.decode64(base64_data)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a blob ID as a string, match on the type-format tag, extract and decode the base64 data and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_blob(blob_id) do
|
||||
blob_tf_tag = SsbBfe.Types.get_blob_type(blob_id)
|
||||
{:ok, decoded_base64_data} = extract_base64_data(blob_id)
|
||||
blob_tf_tag <> decoded_base64_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a boolean value and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_bool(true), do: <<6, 1, 1>>
|
||||
|
||||
def encode_bool(false), do: <<6, 1, 0>>
|
||||
|
||||
@doc """
|
||||
Take an encrypted box as a string, match on the type-format tag, extract and decode the base64 data and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_box(box_str) do
|
||||
box_tf_tag = SsbBfe.Types.get_box_type(box_str)
|
||||
{:ok, decoded_base64_data} = extract_base64_data(box_str, ".")
|
||||
box_tf_tag <> decoded_base64_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a feed ID as a string, match on the type-format tag, extract and decode the base64 data and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_feed(feed_id) do
|
||||
feed_tf_tag = SsbBfe.Types.get_feed_type(feed_id)
|
||||
{:ok, decoded_base64_data} = extract_base64_data(feed_id)
|
||||
feed_tf_tag <> decoded_base64_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a message ID as a string, match on the type-format tag, extract and decode the base64 data and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_msg(msg_id) do
|
||||
msg_tf_tag = SsbBfe.Types.get_msg_type(msg_id)
|
||||
{:ok, decoded_base64_data} = extract_base64_data(msg_id)
|
||||
msg_tf_tag <> decoded_base64_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a `nil` value and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_nil(), do: <<6, 2>>
|
||||
|
||||
def encode_sig(sig) do
|
||||
{:ok, decoded_base64_data} = extract_base64_data(sig, ".sig.ed25519")
|
||||
<<4, 0>> <> decoded_base64_data
|
||||
@doc """
|
||||
Take a signature ID as a string, match on the type-format tag, extract and decode the base64 data and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_sig(sig_id) do
|
||||
sig_tf_tag = SsbBfe.Types.get_sig_type(sig_id)
|
||||
{:ok, decoded_base64_data} = extract_base64_data(sig_id, ".sig.ed25519")
|
||||
sig_tf_tag <> decoded_base64_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a string value and return the encoded bytes representing the TFD.
|
||||
"""
|
||||
def encode_str(str), do: <<6, 0>> <> str
|
||||
|
||||
# def encode_uri(uri)
|
||||
end
|
||||
end
|
||||
|
@ -1,17 +1,21 @@
|
||||
defmodule SsbBfe.Types do
|
||||
@doc ~S"""
|
||||
@doc """
|
||||
Take a blob ID as a string and return the encoded bytes representing the blob
|
||||
type-format. Return `nil` if the ID does not end with `.sha256`.
|
||||
type-format. Throw an error if the ID does not end with `.sha256`.
|
||||
"""
|
||||
def get_blob_type(blob_id) do
|
||||
if String.ends_with?(blob_id, ".sha256") do
|
||||
<<2, 0>>
|
||||
cond do
|
||||
String.ends_with?(blob_id, ".sha256") ->
|
||||
<<2, 0>>
|
||||
|
||||
true ->
|
||||
throw({:unknown_format, blob_id})
|
||||
end
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
@doc """
|
||||
Take a box as a string and return the encoded bytes representing the box
|
||||
type-format. Return `nil` if the ID does not end with `.box` or `.box2`.
|
||||
type-format. Throw an error if the ID does not end with `.box` or `.box2`.
|
||||
"""
|
||||
def get_box_type(boxed_str) do
|
||||
cond do
|
||||
@ -22,23 +26,27 @@ defmodule SsbBfe.Types do
|
||||
<<5, 1>>
|
||||
|
||||
true ->
|
||||
nil
|
||||
throw({:unknown_format, boxed_str})
|
||||
end
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
@doc """
|
||||
Take a feed ID (key) as a string and return the encoded bytes representing
|
||||
the feed type-format. Return `nil` if the ID does not end with `.ed25519`.
|
||||
the feed type-format. Throw an error if the ID does not end with `.ed25519`.
|
||||
"""
|
||||
def get_feed_type(feed_id) do
|
||||
if String.ends_with?(feed_id, ".ed25519") do
|
||||
<<0, 0>>
|
||||
cond do
|
||||
String.ends_with?(feed_id, ".ed25519") ->
|
||||
<<0, 0>>
|
||||
|
||||
true ->
|
||||
throw({:unknown_format, feed_id})
|
||||
end
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
@doc """
|
||||
Take a message ID as a string and return the encoded bytes representing
|
||||
the message type-format. Return `nil` if the ID does not end with `.sha256`
|
||||
the message type-format. Throw an error if the ID does not end with `.sha256`
|
||||
or `.cloaked`.
|
||||
"""
|
||||
def get_msg_type(msg_id) do
|
||||
@ -50,7 +58,21 @@ defmodule SsbBfe.Types do
|
||||
<<1, 2>>
|
||||
|
||||
true ->
|
||||
nil
|
||||
throw({:unknown_format, msg_id})
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Take a signature ID as a string and return the encoded bytes representing
|
||||
the signature type-format. Throw an error if the ID does not end with `.sig.ed25519`.
|
||||
"""
|
||||
def get_sig_type(sig_id) do
|
||||
cond do
|
||||
String.ends_with?(sig_id, ".sig.ed25519") ->
|
||||
<<4, 0>>
|
||||
|
||||
true ->
|
||||
throw({:unknown_format, sig_id})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -5,22 +5,39 @@ defmodule SsbBfeTest do
|
||||
setup do
|
||||
[
|
||||
blob: "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256",
|
||||
blob_encoded: <<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249, 127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>>,
|
||||
blob_encoded:
|
||||
<<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249,
|
||||
127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>>,
|
||||
bool_true_encoded: <<6, 1, 1>>,
|
||||
bool_false_encoded: <<6, 1, 0>>,
|
||||
box1: "bG92ZSBjb2xsYXBzZXMgc3BhY2V0aW1l.box",
|
||||
box1_encoded: <<5, 0, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112, 97, 99, 101, 116, 105, 109, 101>>,
|
||||
box1_encoded:
|
||||
<<5, 0, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112,
|
||||
97, 99, 101, 116, 105, 109, 101>>,
|
||||
box2: "bG92ZSBjb2xsYXBzZXMgc3BhY2V0aW1l.box2",
|
||||
box2_encoded: <<5, 1, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112, 97, 99, 101, 116, 105, 109, 101>>,
|
||||
box2_encoded:
|
||||
<<5, 1, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112,
|
||||
97, 99, 101, 116, 105, 109, 101>>,
|
||||
feed_classic: "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519",
|
||||
feed_classic_encoded: <<0, 0, 119, 252, 195, 188, 91, 48, 21, 180, 26, 96, 151, 52, 222, 46, 59, 11, 208, 160, 13, 235, 254, 252, 15, 16, 65, 39, 198, 230, 95, 210, 17, 252>>,
|
||||
feed_classic_encoded:
|
||||
<<0, 0, 119, 252, 195, 188, 91, 48, 21, 180, 26, 96, 151, 52, 222, 46, 59, 11, 208, 160,
|
||||
13, 235, 254, 252, 15, 16, 65, 39, 198, 230, 95, 210, 17, 252>>,
|
||||
msg_classic: "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256",
|
||||
msg_classic_encoded: <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>>,
|
||||
msg_classic_encoded:
|
||||
<<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166,
|
||||
252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>>,
|
||||
nil_encoded: <<6, 2>>,
|
||||
sig: "nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519",
|
||||
sig_encoded: <<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236, 99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10, 244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180, 61, 175, 14, 77, 65, 210, 224, 12, 5>>,
|
||||
sig:
|
||||
"nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519",
|
||||
sig_encoded:
|
||||
<<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236,
|
||||
99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10,
|
||||
244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180,
|
||||
61, 175, 14, 77, 65, 210, 224, 12, 5>>,
|
||||
str: "golden ripples in the meshwork",
|
||||
str_encoded: <<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110, 32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>>
|
||||
str_encoded:
|
||||
<<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110,
|
||||
32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>>
|
||||
]
|
||||
end
|
||||
|
||||
@ -28,7 +45,7 @@ defmodule SsbBfeTest do
|
||||
|
||||
test "classic feed is encoded correctly", context do
|
||||
encoded_feed = SsbBfe.encode(context.feed_classic)
|
||||
|
||||
|
||||
assert encoded_feed == context.feed_classic_encoded
|
||||
end
|
||||
|
||||
@ -91,7 +108,10 @@ defmodule SsbBfeTest do
|
||||
test "map is encoded correctly", context do
|
||||
encoded_map = SsbBfe.encode(%{"bool" => false, "feed" => context.feed_classic})
|
||||
|
||||
assert encoded_map == %{"bool" => context.bool_false_encoded, "feed" => context.feed_classic_encoded}
|
||||
assert encoded_map == %{
|
||||
"bool" => context.bool_false_encoded,
|
||||
"feed" => context.feed_classic_encoded
|
||||
}
|
||||
end
|
||||
|
||||
test "tuple is encoded correctly", context do
|
||||
@ -131,7 +151,7 @@ defmodule SsbBfeTest do
|
||||
|
||||
assert decoded_box == context.box1
|
||||
end
|
||||
|
||||
|
||||
test "box2 is decoded correctly", context do
|
||||
decoded_box2 = SsbBfe.decode(context.box2_encoded)
|
||||
|
||||
@ -159,17 +179,22 @@ defmodule SsbBfeTest do
|
||||
end
|
||||
|
||||
test "list is decoded correctly", context do
|
||||
decoded_list = SsbBfe.decode([context.bool_true_encoded, context.nil_encoded, context.str_encoded])
|
||||
decoded_list =
|
||||
SsbBfe.decode([context.bool_true_encoded, context.nil_encoded, context.str_encoded])
|
||||
|
||||
assert decoded_list == [true, nil, context.str]
|
||||
end
|
||||
|
||||
test "map is decoded correctly", context do
|
||||
decoded_map = SsbBfe.decode(%{"bool" => context.bool_false_encoded, "feed" => context.feed_classic_encoded})
|
||||
decoded_map =
|
||||
SsbBfe.decode(%{
|
||||
"bool" => context.bool_false_encoded,
|
||||
"feed" => context.feed_classic_encoded
|
||||
})
|
||||
|
||||
assert decoded_map == %{"bool" => false, "feed" => context.feed_classic}
|
||||
end
|
||||
|
||||
|
||||
test "tuple is decoded correctly", context do
|
||||
decoded_tuple = SsbBfe.decode({7, context.msg_classic_encoded})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user