Current section
Files
Jump to
Current section
Files
src/gose@cose.erl
-module(gose@cose).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gose/cose.gleam").
-export([content_type_to_cbor/1, header_to_cbor/1, headers_to_cbor/1, algorithm/1, critical/1, content_type/1, kid/1, iv/1, partial_iv/1, header_from_cbor/1, headers_from_cbor/1]).
-export_type([content_type/0, header/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Typed accessors and builders for COSE message header parameters.\n"
"\n"
" ## Phantom-state vocabulary\n"
"\n"
" Each COSE message module uses a phantom state type named after the\n"
" RFC 9052 operation it performs: `Sign1` uses `Unsigned`/`Signed`,\n"
" `Encrypt0` and `Encrypt` use `Unencrypted`/`Encrypted`, `Mac0` uses\n"
" `Untagged`/`Tagged`, and `Sign` uses `Building`/`Signed` for its builder\n"
" body. The names match the RFC terminology rather than a single uniform\n"
" vocabulary.\n"
).
-type content_type() :: text_plain |
octet_stream |
json |
cbor |
cwt |
cose_sign |
cose_sign1 |
cose_encrypt |
cose_encrypt0 |
cose_mac |
cose_mac0 |
cose_key |
cose_key_set |
{int_content_type, integer()} |
{text_content_type, binary()}.
-type header() :: {alg, integer()} |
{crit, list(integer())} |
{content_type, content_type()} |
{kid, bitstring()} |
{iv, bitstring()} |
{partial_iv, bitstring()} |
{unknown, gose@cbor:value(), gose@cbor:value()}.
-file("src/gose/cose.gleam", 156).
?DOC(false).
-spec content_type_to_cbor(content_type()) -> gose@cbor:value().
content_type_to_cbor(Ct) ->
case Ct of
text_plain ->
{int, 0};
octet_stream ->
{int, 42};
json ->
{int, 50};
cbor ->
{int, 60};
cwt ->
{int, 61};
cose_sign ->
{int, 101};
cose_sign1 ->
{int, 102};
cose_encrypt ->
{int, 103};
cose_encrypt0 ->
{int, 104};
cose_mac ->
{int, 105};
cose_mac0 ->
{int, 106};
cose_key ->
{int, 10001};
cose_key_set ->
{int, 10002};
{int_content_type, N} ->
{int, N};
{text_content_type, S} ->
{text, S}
end.
-file("src/gose/cose.gleam", 100).
?DOC(false).
-spec header_to_cbor(header()) -> {gose@cbor:value(), gose@cbor:value()}.
header_to_cbor(Header) ->
case Header of
{alg, Id} ->
{{int, 1}, {int, Id}};
{crit, Labels} ->
{{int, 2},
{array,
gleam@list:map(Labels, fun(Field@0) -> {int, Field@0} end)}};
{content_type, Ct} ->
{{int, 3}, content_type_to_cbor(Ct)};
{kid, K} ->
{{int, 4}, {bytes, K}};
{iv, V} ->
{{int, 5}, {bytes, V}};
{partial_iv, V@1} ->
{{int, 6}, {bytes, V@1}};
{unknown, Key, Value} ->
{Key, Value}
end.
-file("src/gose/cose.gleam", 151).
?DOC(false).
-spec headers_to_cbor(list(header())) -> list({gose@cbor:value(),
gose@cbor:value()}).
headers_to_cbor(Headers) ->
gleam@list:map(Headers, fun header_to_cbor/1).
-file("src/gose/cose.gleam", 176).
-spec content_type_from_cbor(gose@cbor:value()) -> {ok, content_type()} |
{error, gose:gose_error()}.
content_type_from_cbor(Value) ->
case Value of
{int, 0} ->
{ok, text_plain};
{int, 42} ->
{ok, octet_stream};
{int, 50} ->
{ok, json};
{int, 60} ->
{ok, cbor};
{int, 61} ->
{ok, cwt};
{int, 101} ->
{ok, cose_sign};
{int, 102} ->
{ok, cose_sign1};
{int, 103} ->
{ok, cose_encrypt};
{int, 104} ->
{ok, cose_encrypt0};
{int, 105} ->
{ok, cose_mac};
{int, 106} ->
{ok, cose_mac0};
{int, 10001} ->
{ok, cose_key};
{int, 10002} ->
{ok, cose_key_set};
{int, N} ->
{ok, {int_content_type, N}};
{text, S} ->
{ok, {text_content_type, S}};
_ ->
{error,
{parse_error,
<<"header label 3 (content type): expected Int or Text"/utf8>>}}
end.
-file("src/gose/cose.gleam", 202).
-spec is_alg(header()) -> boolean().
is_alg(Header) ->
case Header of
{alg, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 50).
?DOC(" Extract the algorithm identifier (label 1).\n").
-spec algorithm(list(header())) -> {ok, integer()} | {error, gose:gose_error()}.
algorithm(Headers) ->
case gleam@list:find(Headers, fun is_alg/1) of
{ok, {alg, Id}} ->
{ok, Id};
_ ->
{error, {parse_error, <<"missing header label 1 (alg)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 209).
-spec is_crit(header()) -> boolean().
is_crit(Header) ->
case Header of
{crit, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 58).
?DOC(" Extract the critical headers list (label 2).\n").
-spec critical(list(header())) -> {ok, list(integer())} |
{error, gose:gose_error()}.
critical(Headers) ->
case gleam@list:find(Headers, fun is_crit/1) of
{ok, {crit, Labels}} ->
{ok, Labels};
_ ->
{error, {parse_error, <<"missing header label 2 (crit)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 216).
-spec is_content_type(header()) -> boolean().
is_content_type(Header) ->
case Header of
{content_type, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 66).
?DOC(" Extract the content type (label 3).\n").
-spec content_type(list(header())) -> {ok, content_type()} |
{error, gose:gose_error()}.
content_type(Headers) ->
case gleam@list:find(Headers, fun is_content_type/1) of
{ok, {content_type, Ct}} ->
{ok, Ct};
_ ->
{error,
{parse_error, <<"missing header label 3 (content type)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 223).
-spec is_kid(header()) -> boolean().
is_kid(Header) ->
case Header of
{kid, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 76).
?DOC(" Extract the key ID (label 4).\n").
-spec kid(list(header())) -> {ok, bitstring()} | {error, gose:gose_error()}.
kid(Headers) ->
case gleam@list:find(Headers, fun is_kid/1) of
{ok, {kid, K}} ->
{ok, K};
_ ->
{error, {parse_error, <<"missing header label 4 (kid)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 230).
-spec is_iv(header()) -> boolean().
is_iv(Header) ->
case Header of
{iv, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 84).
?DOC(" Extract the IV (label 5).\n").
-spec iv(list(header())) -> {ok, bitstring()} | {error, gose:gose_error()}.
iv(Headers) ->
case gleam@list:find(Headers, fun is_iv/1) of
{ok, {iv, V}} ->
{ok, V};
_ ->
{error, {parse_error, <<"missing header label 5 (IV)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 237).
-spec is_partial_iv(header()) -> boolean().
is_partial_iv(Header) ->
case Header of
{partial_iv, _} ->
true;
_ ->
false
end.
-file("src/gose/cose.gleam", 92).
?DOC(" Extract the partial IV (label 6).\n").
-spec partial_iv(list(header())) -> {ok, bitstring()} |
{error, gose:gose_error()}.
partial_iv(Headers) ->
case gleam@list:find(Headers, fun is_partial_iv/1) of
{ok, {partial_iv, V}} ->
{ok, V};
_ ->
{error,
{parse_error, <<"missing header label 6 (Partial IV)"/utf8>>}}
end.
-file("src/gose/cose.gleam", 244).
-spec parse_int_list(list(gose@cbor:value()), list(integer())) -> {ok,
list(integer())} |
{error, gose:gose_error()}.
parse_int_list(Values, Acc) ->
case Values of
[] ->
{ok, lists:reverse(Acc)};
[{int, N} | Rest] ->
parse_int_list(Rest, [N | Acc]);
_ ->
{error,
{parse_error,
<<"header label 2 (crit): expected array of Int"/utf8>>}}
end.
-file("src/gose/cose.gleam", 113).
?DOC(false).
-spec header_from_cbor({gose@cbor:value(), gose@cbor:value()}) -> {ok, header()} |
{error, gose:gose_error()}.
header_from_cbor(Pair) ->
case Pair of
{{int, 1}, {int, Id}} ->
{ok, {alg, Id}};
{{int, 1}, _} ->
{error,
{parse_error, <<"header label 1 (alg): expected Int"/utf8>>}};
{{int, 2}, {array, Values}} ->
gleam@result:map(
parse_int_list(Values, []),
fun(Labels) -> {crit, Labels} end
);
{{int, 2}, _} ->
{error,
{parse_error, <<"header label 2 (crit): expected Array"/utf8>>}};
{{int, 3}, Value} ->
gleam@result:map(
content_type_from_cbor(Value),
fun(Ct) -> {content_type, Ct} end
);
{{int, 4}, {bytes, K}} ->
{ok, {kid, K}};
{{int, 4}, _} ->
{error,
{parse_error, <<"header label 4 (kid): expected Bytes"/utf8>>}};
{{int, 5}, {bytes, V}} ->
{ok, {iv, V}};
{{int, 5}, _} ->
{error,
{parse_error, <<"header label 5 (IV): expected Bytes"/utf8>>}};
{{int, 6}, {bytes, V@1}} ->
{ok, {partial_iv, V@1}};
{{int, 6}, _} ->
{error,
{parse_error,
<<"header label 6 (Partial IV): expected Bytes"/utf8>>}};
{Key, Value@1} ->
{ok, {unknown, Key, Value@1}}
end.
-file("src/gose/cose.gleam", 144).
?DOC(false).
-spec headers_from_cbor(list({gose@cbor:value(), gose@cbor:value()})) -> {ok,
list(header())} |
{error, gose:gose_error()}.
headers_from_cbor(Pairs) ->
gleam@list:try_map(Pairs, fun header_from_cbor/1).