Compare commits
3 Commits
68a0c3d623
...
a1be8cbc14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1be8cbc14 | ||
|
|
3822bb69c9 | ||
|
|
6506fc91bd |
68
src/hz.erl
68
src/hz.erl
@ -1658,6 +1658,12 @@ normalize_opaque_type(T, Types) ->
|
||||
true -> {ok, true, T, T}
|
||||
end.
|
||||
|
||||
% This function evaluates type aliases in a loop, until eventually a usable
|
||||
% definition is found.
|
||||
%
|
||||
% It also evaluates built-in and standard library types such as options and
|
||||
% names, to their defined variant representation, as well as evaluating
|
||||
% certain binary types like hash, fp, and fr, into their byte representations.
|
||||
% FIXME detect infinite loops
|
||||
% FIXME detect builtins with the wrong number of arguments
|
||||
% FIXME should nullary types have an empty list of arguments added before now?
|
||||
@ -1665,6 +1671,10 @@ normalize_opaque_type({option, [T]}, _Types, IsFirst) ->
|
||||
% Just like user-made ADTs, 'option' is considered part of the type, and so
|
||||
% options are considered normalised.
|
||||
{ok, IsFirst, {option, [T]}, {variant, [{"None", []}, {"Some", [T]}]}};
|
||||
normalize_opaque_type(hash, _Types, IsFirst) ->
|
||||
% For coercion purposes, hash is indistinguishable from bytes(32), so we
|
||||
% treat it like a type alias.
|
||||
{ok, IsFirst, hash, {bytes, [32]}};
|
||||
normalize_opaque_type(T, Types, IsFirst) when is_list(T) ->
|
||||
normalize_opaque_type({T, []}, Types, IsFirst);
|
||||
normalize_opaque_type({T, TypeArgs}, Types, IsFirst) when is_list(T) ->
|
||||
@ -1709,7 +1719,10 @@ normalize_opaque_type3(NextT, Types) ->
|
||||
|
||||
% Strings indicate names that should be substituted. Atoms indicate built in
|
||||
% types, which don't need to be expanded, except for option.
|
||||
% TODO: Stop calling this, so that we can stop redundantly enumerating all the
|
||||
% built in types.
|
||||
type_is_expanded({option, _}) -> false;
|
||||
type_is_expanded(hash) -> false;
|
||||
type_is_expanded(X) when is_atom(X) -> true;
|
||||
type_is_expanded({X, _}) when is_atom(X) -> true;
|
||||
type_is_expanded(_) -> false.
|
||||
@ -1820,6 +1833,11 @@ coerce({O, N, contract}, S, to_fate) ->
|
||||
coerce({_, _, contract}, {contract, Bin}, from_fate) ->
|
||||
Address = gmser_api_encoder:encode(contract_pubkey, Bin),
|
||||
{ok, unicode:characters_to_list(Address)};
|
||||
coerce({_, _, signature}, S, to_fate) when is_binary(S) andalso (byte_size(S) =:= 64) ->
|
||||
% If it is a binary of 64 bytes then it can be used as is... If it is an
|
||||
% sg_... string of 64 bytes, then it is too short to be valid, so just
|
||||
% interpret it as a binary directly.
|
||||
{ok, S};
|
||||
coerce({O, N, signature}, S, to_fate) ->
|
||||
coerce_chain_object(O, N, signature, signature, S);
|
||||
coerce({_, _, signature}, Bin, from_fate) ->
|
||||
@ -1850,6 +1868,18 @@ coerce({O, N, string}, Str, Direction) ->
|
||||
end;
|
||||
coerce({_, _, char}, Val, _Direction) when is_integer(Val) ->
|
||||
{ok, Val};
|
||||
coerce({O, N, char}, Str, to_fate) ->
|
||||
Result = unicode:characters_to_list(Str),
|
||||
case Result of
|
||||
{error, _, _} ->
|
||||
single_error({invalid, O, N, Str});
|
||||
{incomplete, _, _} ->
|
||||
single_error({invalid, O, N, Str});
|
||||
[C] ->
|
||||
{ok, C};
|
||||
_ ->
|
||||
single_error({invalid, O, N, Str})
|
||||
end;
|
||||
coerce({O, N, {bytes, [Count]}}, Bytes, _Direction) when is_bitstring(Bytes) ->
|
||||
coerce_bytes(O, N, Count, Bytes);
|
||||
coerce({_, _, bits}, {bits, Num}, from_fate) ->
|
||||
@ -2502,6 +2532,15 @@ coerce_signature_test() ->
|
||||
249,2,3,85,173,106,150,243,253,89,128,248,52,195,140,95,114,
|
||||
233,110,119,143,206,137,124,36,63,154,85,7>>).
|
||||
|
||||
coerce_signature_binary_test() ->
|
||||
{ok, Type} = annotate_type(signature, #{}),
|
||||
Binary = <<231,4,97,129,16,173,37,42,194,249,28,94,134,163,208,84,22,135,
|
||||
169,85,212,142,14,12,233,252,97,50,193,158,229,51,123,206,222,
|
||||
249,2,3,85,173,106,150,243,253,89,128,248,52,195,140,95,114,
|
||||
233,110,119,143,206,137,124,36,63,154,85,7>>,
|
||||
{ok, Binary} = coerce(Type, Binary, to_fate),
|
||||
ok.
|
||||
|
||||
coerce_bool_test() ->
|
||||
{ok, Type} = annotate_type(boolean, #{}),
|
||||
try_coerce(Type, true, true),
|
||||
@ -2546,6 +2585,19 @@ coerce_char_test() ->
|
||||
{ok, Type} = annotate_type(char, #{}),
|
||||
try_coerce(Type, $?, $?).
|
||||
|
||||
coerce_unicode_test() ->
|
||||
{ok, Type} = annotate_type(char, #{}),
|
||||
% Latin Small Letter C with cedilla and acute
|
||||
{ok, $ḉ} = coerce(Type, <<"ḉ"/utf8>>, to_fate),
|
||||
ok.
|
||||
|
||||
coerce_hash_test() ->
|
||||
{ok, Type} = annotate_type(hash, #{}),
|
||||
Hash = list_to_binary(lists:seq(1,32)),
|
||||
try_coerce(Type, Hash, Hash),
|
||||
ok.
|
||||
|
||||
|
||||
|
||||
%%% Complex AACI paramter and namespace tests
|
||||
|
||||
@ -2642,20 +2694,20 @@ obscure_aaci_test() ->
|
||||
entrypoint any_bytes(): bytes() = Bytes.to_any_size(#112233)
|
||||
entrypoint bits(): bits = Bits.all
|
||||
entrypoint character(): char = 'a'
|
||||
entrypoint hash(): hash = #00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF
|
||||
",
|
||||
{ok, AACI} = aaci_from_string(Contract),
|
||||
|
||||
IntAnnotated = {integer, already_normalized, integer},
|
||||
OptionFlat = {variant, [{"None", []}, {"Some", [IntAnnotated]}]},
|
||||
OptionAnnotated = {{option, [integer]}, already_normalized, OptionFlat},
|
||||
{ok, {[], OptionAnnotated}} = aaci_lookup_spec(AACI, "options"),
|
||||
{ok, {[], {{option, [integer]}, _, _}}} = aaci_lookup_spec(AACI, "options"),
|
||||
|
||||
{ok, {[], {_, _, {bytes, [4]}}}} = aaci_lookup_spec(AACI, "fixed_bytes"),
|
||||
{ok, {[], {_, _, {bytes, [any]}}}} = aaci_lookup_spec(AACI, "any_bytes"),
|
||||
{ok, {[], {{bytes, [4]}, _, _}}} = aaci_lookup_spec(AACI, "fixed_bytes"),
|
||||
{ok, {[], {{bytes, [any]}, _, _}}} = aaci_lookup_spec(AACI, "any_bytes"),
|
||||
|
||||
{ok, {[], {_, _, bits}}} = aaci_lookup_spec(AACI, "bits"),
|
||||
{ok, {[], {bits, _, _}}} = aaci_lookup_spec(AACI, "bits"),
|
||||
|
||||
{ok, {[], {_, _, char}}} = aaci_lookup_spec(AACI, "character"),
|
||||
{ok, {[], {char, _, _}}} = aaci_lookup_spec(AACI, "character"),
|
||||
|
||||
{ok, {[], {hash, _, _}}} = aaci_lookup_spec(AACI, "hash"),
|
||||
|
||||
ok.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user