6d7ab1e4ad
Gajumaru Serialization Tests / tests (push) Successful in 10s
This branch contains a proof-of-concept exploration of representing
the RLP (gmser_rlp) and gmserialization layers using ASN.1 with
DER encoding.
Goals of the experiment:
- Model the static serialization templates and dynamic types in ASN.1.
- Demonstrate reliable detection of legacy RLP data vs. new DER data
(first byte >= 0xC0 for RLP lists vs. 0x30 for DER SEQUENCE).
- Evaluate wire-size overhead of standard DER TLV encoding compared
to the extremely compact RLP prefix encoding.
- Verify that the DER path produces deterministic output suitable
for hashing (idempotent serialization).
Key files:
- GajumaruSerialization.asn -- the ASN.1 schema
- GajumaruSerialization.{erl,hrl} -- generated encoder/decoder
- detect_demo.erl, size_comparison.erl -- supporting test code
Findings (high level):
- Detection via first byte works cleanly.
- DER is fully deterministic for hashing when the same value is given.
- Small objects pay a significant size overhead (often 3-6x) due to
TLV tags/lengths and field names in the generic path.
- Concrete SEQUENCE definitions are much more compact than the
generic templateFields representation.
- Large payloads have acceptable relative overhead.
This is NOT production code. It was created to answer feasibility
questions around ASN.1 modeling, format detection, determinism,
and size characteristics.
Branch created from uw-new-acs for isolated experimentation.
1403 lines
41 KiB
Erlang
1403 lines
41 KiB
Erlang
%% Generated by the Erlang ASN.1 BER compiler. Version: 5.4.3
|
|
%% Purpose: Encoding and decoding of the types in GajumaruSerialization.
|
|
|
|
-module('GajumaruSerialization').
|
|
-moduledoc false.
|
|
-compile(nowarn_unused_vars).
|
|
-dialyzer(no_improper_lists).
|
|
-dialyzer(no_match).
|
|
-include("GajumaruSerialization.hrl").
|
|
-asn1_info([{vsn,'5.4.3'},
|
|
{module,'GajumaruSerialization'},
|
|
{options,[der,{outdir,"asn1"},{i,"."},{i,"asn1"}]}]).
|
|
|
|
-export([encoding_rule/0,maps/0,bit_string_format/0,
|
|
legacy_erlang_types/0]).
|
|
-export(['dialyzer-suppressions'/1]).
|
|
-export([
|
|
enc_GajumaruData/2,
|
|
enc_Content/2,
|
|
enc_TemplateFields/2,
|
|
enc_TemplateField/2,
|
|
enc_Value/2,
|
|
enc_KeyValue/2,
|
|
enc_Id/2,
|
|
enc_Account/2,
|
|
enc_SignedTx/2,
|
|
enc_ContractCode/2,
|
|
enc_ContractV1/2,
|
|
enc_ContractV2/2,
|
|
enc_ContractV3/2,
|
|
enc_TypeInfoV1/2,
|
|
enc_TypeInfoV3/2
|
|
]).
|
|
|
|
-export([
|
|
dec_GajumaruData/2,
|
|
dec_Content/2,
|
|
dec_TemplateFields/2,
|
|
dec_TemplateField/2,
|
|
dec_Value/2,
|
|
dec_KeyValue/2,
|
|
dec_Id/2,
|
|
dec_Account/2,
|
|
dec_SignedTx/2,
|
|
dec_ContractCode/2,
|
|
dec_ContractV1/2,
|
|
dec_ContractV2/2,
|
|
dec_ContractV3/2,
|
|
dec_TypeInfoV1/2,
|
|
dec_TypeInfoV3/2
|
|
]).
|
|
|
|
-export([info/0]).
|
|
|
|
-export([encode/2,decode/2]).
|
|
|
|
encoding_rule() -> ber.
|
|
|
|
maps() -> false.
|
|
|
|
bit_string_format() -> bitstring.
|
|
|
|
legacy_erlang_types() -> false.
|
|
|
|
encode(Type, Data) ->
|
|
try iolist_to_binary(element(1, encode_disp(Type, Data))) of
|
|
Bytes ->
|
|
{ok,Bytes}
|
|
catch
|
|
Class:Exception:Stk when Class =:= error; Class =:= exit ->
|
|
case Exception of
|
|
{error,{asn1,Reason}} ->
|
|
{error,{asn1,{Reason,Stk}}};
|
|
Reason ->
|
|
{error,{asn1,{Reason,Stk}}}
|
|
end
|
|
end.
|
|
|
|
|
|
decode(Type, Data) ->
|
|
try
|
|
Result = decode_disp(Type, element(1, ber_decode_nif(Data))),
|
|
{ok,Result}
|
|
catch
|
|
Class:Exception:Stk when Class =:= error; Class =:= exit ->
|
|
case Exception of
|
|
{error,{asn1,Reason}} ->
|
|
{error,{asn1,{Reason,Stk}}};
|
|
Reason ->
|
|
{error,{asn1,{Reason,Stk}}}
|
|
end
|
|
end.
|
|
|
|
encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data);
|
|
encode_disp('Content', Data) -> enc_Content(Data);
|
|
encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data);
|
|
encode_disp('TemplateField', Data) -> enc_TemplateField(Data);
|
|
encode_disp('Value', Data) -> enc_Value(Data);
|
|
encode_disp('KeyValue', Data) -> enc_KeyValue(Data);
|
|
encode_disp('Id', Data) -> enc_Id(Data);
|
|
encode_disp('Account', Data) -> enc_Account(Data);
|
|
encode_disp('SignedTx', Data) -> enc_SignedTx(Data);
|
|
encode_disp('ContractCode', Data) -> enc_ContractCode(Data);
|
|
encode_disp('ContractV1', Data) -> enc_ContractV1(Data);
|
|
encode_disp('ContractV2', Data) -> enc_ContractV2(Data);
|
|
encode_disp('ContractV3', Data) -> enc_ContractV3(Data);
|
|
encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data);
|
|
encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data);
|
|
encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}).
|
|
|
|
decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data);
|
|
decode_disp('Content', Data) -> dec_Content(Data);
|
|
decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data);
|
|
decode_disp('TemplateField', Data) -> dec_TemplateField(Data);
|
|
decode_disp('Value', Data) -> dec_Value(Data);
|
|
decode_disp('KeyValue', Data) -> dec_KeyValue(Data);
|
|
decode_disp('Id', Data) -> dec_Id(Data);
|
|
decode_disp('Account', Data) -> dec_Account(Data);
|
|
decode_disp('SignedTx', Data) -> dec_SignedTx(Data);
|
|
decode_disp('ContractCode', Data) -> dec_ContractCode(Data);
|
|
decode_disp('ContractV1', Data) -> dec_ContractV1(Data);
|
|
decode_disp('ContractV2', Data) -> dec_ContractV2(Data);
|
|
decode_disp('ContractV3', Data) -> dec_ContractV3(Data);
|
|
decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data);
|
|
decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data);
|
|
decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}).
|
|
|
|
info() ->
|
|
case ?MODULE:module_info(attributes) of
|
|
Attributes when is_list(Attributes) ->
|
|
case lists:keyfind(asn1_info, 1, Attributes) of
|
|
{_,Info} when is_list(Info) ->
|
|
Info;
|
|
_ ->
|
|
[]
|
|
end;
|
|
_ ->
|
|
[]
|
|
end.
|
|
|
|
|
|
%%================================
|
|
%% GajumaruData
|
|
%%================================
|
|
enc_GajumaruData(Val) ->
|
|
enc_GajumaruData(Val, [<<48>>]).
|
|
|
|
enc_GajumaruData(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute tag(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute vsn(2) with type INTEGER
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_integer(Cindex2, [<<129>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute content(3) External GajumaruSerialization:Content
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = 'enc_Content'(Cindex3, [<<162>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_GajumaruData(Tlv) ->
|
|
dec_GajumaruData(Tlv, [16]).
|
|
|
|
dec_GajumaruData(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute tag(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_integer(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute vsn(2) with type INTEGER
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = decode_integer(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute content(3) External GajumaruSerialization:Content
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = 'dec_Content'(V3, [131074]),
|
|
|
|
case Tlv4 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'GajumaruData',Term1,Term2,Term3},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% Content
|
|
%%================================
|
|
enc_Content(Val) ->
|
|
enc_Content(Val, []).
|
|
|
|
enc_Content(Val, TagIn) ->
|
|
{EncBytes,EncLen} = case element(1,Val) of
|
|
templateFields ->
|
|
'enc_TemplateFields'(element(2,Val), [<<160>>]);
|
|
account ->
|
|
'enc_Account'(element(2,Val), [<<161>>]);
|
|
signedTx ->
|
|
'enc_SignedTx'(element(2,Val), [<<162>>]);
|
|
contract ->
|
|
'enc_ContractCode'(element(2,Val), [<<163>>]);
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_type,Else}}})
|
|
end,
|
|
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
|
|
|
|
|
|
dec_Content(Tlv) ->
|
|
dec_Content(Tlv, []).
|
|
|
|
dec_Content(Tlv, TagIn) ->
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of
|
|
|
|
%% 'templateFields'
|
|
{131072, V1} ->
|
|
{templateFields, 'dec_TemplateFields'(V1, [])};
|
|
|
|
|
|
%% 'account'
|
|
{131073, V1} ->
|
|
{account, 'dec_Account'(V1, [])};
|
|
|
|
|
|
%% 'signedTx'
|
|
{131074, V1} ->
|
|
{signedTx, 'dec_SignedTx'(V1, [])};
|
|
|
|
|
|
%% 'contract'
|
|
{131075, V1} ->
|
|
{contract, 'dec_ContractCode'(V1, [])};
|
|
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_tag,Else}}})
|
|
end
|
|
.
|
|
|
|
|
|
%%================================
|
|
%% TemplateFields
|
|
%%================================
|
|
enc_TemplateFields(Val) ->
|
|
enc_TemplateFields(Val, [<<48>>]).
|
|
|
|
enc_TemplateFields(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_TemplateFields_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_TemplateFields_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_TemplateFields_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_TemplateField'(H, [<<48>>]),
|
|
'enc_TemplateFields_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_TemplateFields(Tlv) ->
|
|
dec_TemplateFields(Tlv, [16]).
|
|
|
|
dec_TemplateFields(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_TemplateField'(V1, [16]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% TemplateField
|
|
%%================================
|
|
enc_TemplateField(Val) ->
|
|
enc_TemplateField(Val, [<<48>>]).
|
|
|
|
enc_TemplateField(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(1) with type IA5String OPTIONAL
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = case Cindex1 of
|
|
asn1_NOVALUE -> {<<>>,0};
|
|
_ ->
|
|
encode_restricted_string(Cindex1, [<<128>>])
|
|
end,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute value(2) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = 'enc_Value'(Cindex2, [<<161>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2],
|
|
LenSoFar = EncLen1 + EncLen2,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_TemplateField(Tlv) ->
|
|
dec_TemplateField(Tlv, [16]).
|
|
|
|
dec_TemplateField(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(1) with type IA5String OPTIONAL
|
|
%%-------------------------------------------------
|
|
{Term1,Tlv2} = case Tlv1 of
|
|
[{131072,V1}|TempTlv2] ->
|
|
{begin
|
|
binary_to_list(decode_restricted_string(V1, []))
|
|
end
|
|
, TempTlv2};
|
|
_ ->
|
|
{ asn1_NOVALUE, Tlv1}
|
|
end,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute value(2) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = 'dec_Value'(V2, [131073]),
|
|
|
|
case Tlv3 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'TemplateField',Term1,Term2},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% Value
|
|
%%================================
|
|
enc_Value(Val) ->
|
|
enc_Value(Val, []).
|
|
|
|
enc_Value(Val, TagIn) ->
|
|
{EncBytes,EncLen} = case element(1,Val) of
|
|
intValue ->
|
|
encode_integer(element(2,Val), [<<128>>]);
|
|
boolValue ->
|
|
encode_boolean(element(2,Val), [<<129>>]);
|
|
binaryValue ->
|
|
encode_restricted_string(element(2,Val), [<<130>>]);
|
|
idValue ->
|
|
'enc_Id'(element(2,Val), [<<163>>]);
|
|
listValue ->
|
|
'enc_Value_listValue'(element(2,Val), [<<164>>]);
|
|
tupleValue ->
|
|
'enc_Value_tupleValue'(element(2,Val), [<<165>>]);
|
|
mapValue ->
|
|
'enc_Value_mapValue'(element(2,Val), [<<166>>]);
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_type,Else}}})
|
|
end,
|
|
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% Value_listValue
|
|
%%================================
|
|
enc_Value_listValue(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_Value_listValue_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_Value_listValue_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_Value_listValue_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_Value'(H, []),
|
|
'enc_Value_listValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% Value_tupleValue
|
|
%%================================
|
|
enc_Value_tupleValue(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_Value_tupleValue_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_Value_tupleValue_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_Value_tupleValue_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_Value'(H, []),
|
|
'enc_Value_tupleValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% Value_mapValue
|
|
%%================================
|
|
enc_Value_mapValue(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_Value_mapValue_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_Value_mapValue_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_Value_mapValue_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_KeyValue'(H, [<<48>>]),
|
|
'enc_Value_mapValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_Value(Tlv) ->
|
|
dec_Value(Tlv, []).
|
|
|
|
dec_Value(Tlv, TagIn) ->
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of
|
|
|
|
%% 'intValue'
|
|
{131072, V1} ->
|
|
{intValue, decode_integer(V1, [])};
|
|
|
|
|
|
%% 'boolValue'
|
|
{131073, V1} ->
|
|
{boolValue, decode_boolean(V1, [])};
|
|
|
|
|
|
%% 'binaryValue'
|
|
{131074, V1} ->
|
|
{binaryValue, decode_octet_string(V1, [])};
|
|
|
|
|
|
%% 'idValue'
|
|
{131075, V1} ->
|
|
{idValue, 'dec_Id'(V1, [])};
|
|
|
|
|
|
%% 'listValue'
|
|
{131076, V1} ->
|
|
{listValue, 'dec_Value_listValue'(V1, [])};
|
|
|
|
|
|
%% 'tupleValue'
|
|
{131077, V1} ->
|
|
{tupleValue, 'dec_Value_tupleValue'(V1, [])};
|
|
|
|
|
|
%% 'mapValue'
|
|
{131078, V1} ->
|
|
{mapValue, 'dec_Value_mapValue'(V1, [])};
|
|
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_tag,Else}}})
|
|
end
|
|
.
|
|
'dec_Value_listValue'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_Value'(V1, []) || V1 <- Tlv1].
|
|
|
|
|
|
'dec_Value_tupleValue'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_Value'(V1, []) || V1 <- Tlv1].
|
|
|
|
|
|
'dec_Value_mapValue'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_KeyValue'(V1, [16]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% KeyValue
|
|
%%================================
|
|
enc_KeyValue(Val) ->
|
|
enc_KeyValue(Val, [<<48>>]).
|
|
|
|
enc_KeyValue(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute key(1) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = 'enc_Value'(Cindex1, [<<160>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute val(2) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = 'enc_Value'(Cindex2, [<<161>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2],
|
|
LenSoFar = EncLen1 + EncLen2,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_KeyValue(Tlv) ->
|
|
dec_KeyValue(Tlv, [16]).
|
|
|
|
dec_KeyValue(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute key(1) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = 'dec_Value'(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute val(2) External GajumaruSerialization:Value
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = 'dec_Value'(V2, [131073]),
|
|
|
|
case Tlv3 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'KeyValue',Term1,Term2},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% Id
|
|
%%================================
|
|
enc_Id(Val) ->
|
|
enc_Id(Val, [<<48>>]).
|
|
|
|
enc_Id(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute type(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute value(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2],
|
|
LenSoFar = EncLen1 + EncLen2,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_Id(Tlv) ->
|
|
dec_Id(Tlv, [16]).
|
|
|
|
dec_Id(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute type(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = begin
|
|
Val1 = decode_integer(V1, [131072]),
|
|
if 0 =< Val1, Val1 =< 255 ->
|
|
Val1;
|
|
true ->
|
|
exit({error,{asn1,bad_range}})
|
|
end
|
|
end,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute value(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = begin
|
|
Val2 = decode_octet_string(V2, [131073]),
|
|
C1 = byte_size(Val2),
|
|
if C1 =:= 32 ->
|
|
Val2;
|
|
true ->
|
|
exit({error,{asn1,bad_range}})
|
|
end
|
|
end,
|
|
|
|
case Tlv3 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'Id',Term1,Term2},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% Account
|
|
%%================================
|
|
enc_Account(Val) ->
|
|
enc_Account(Val, [<<48>>]).
|
|
|
|
enc_Account(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute foo(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute bar(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2],
|
|
LenSoFar = EncLen1 + EncLen2,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_Account(Tlv) ->
|
|
dec_Account(Tlv, [16]).
|
|
|
|
dec_Account(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute foo(1) with type INTEGER
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_integer(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute bar(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = decode_octet_string(V2, [131073]),
|
|
|
|
case Tlv3 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'Account',Term1,Term2},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% SignedTx
|
|
%%================================
|
|
enc_SignedTx(Val) ->
|
|
enc_SignedTx(Val, [<<48>>]).
|
|
|
|
enc_SignedTx(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute signatures(1) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = 'enc_SignedTx_signatures'(Cindex1, [<<160>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute transaction(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2],
|
|
LenSoFar = EncLen1 + EncLen2,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
|
|
%%================================
|
|
%% SignedTx_signatures
|
|
%%================================
|
|
enc_SignedTx_signatures(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_SignedTx_signatures_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_SignedTx_signatures_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_SignedTx_signatures_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]),
|
|
'enc_SignedTx_signatures_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_SignedTx(Tlv) ->
|
|
dec_SignedTx(Tlv, [16]).
|
|
|
|
dec_SignedTx(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute signatures(1) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = 'dec_SignedTx_signatures'(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute transaction(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = decode_octet_string(V2, [131073]),
|
|
|
|
case Tlv3 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'SignedTx',Term1,Term2},
|
|
Res1.
|
|
'dec_SignedTx_signatures'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
[decode_octet_string(V1, [4]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractCode
|
|
%%================================
|
|
enc_ContractCode(Val) ->
|
|
enc_ContractCode(Val, []).
|
|
|
|
enc_ContractCode(Val, TagIn) ->
|
|
{EncBytes,EncLen} = case element(1,Val) of
|
|
v1 ->
|
|
'enc_ContractV1'(element(2,Val), [<<160>>]);
|
|
v2 ->
|
|
'enc_ContractV2'(element(2,Val), [<<161>>]);
|
|
v3 ->
|
|
'enc_ContractV3'(element(2,Val), [<<162>>]);
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_type,Else}}})
|
|
end,
|
|
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
|
|
|
|
|
|
dec_ContractCode(Tlv) ->
|
|
dec_ContractCode(Tlv, []).
|
|
|
|
dec_ContractCode(Tlv, TagIn) ->
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of
|
|
|
|
%% 'v1'
|
|
{131072, V1} ->
|
|
{v1, 'dec_ContractV1'(V1, [])};
|
|
|
|
|
|
%% 'v2'
|
|
{131073, V1} ->
|
|
{v2, 'dec_ContractV2'(V1, [])};
|
|
|
|
|
|
%% 'v3'
|
|
{131074, V1} ->
|
|
{v3, 'dec_ContractV3'(V1, [])};
|
|
|
|
Else ->
|
|
exit({error,{asn1,{invalid_choice_tag,Else}}})
|
|
end
|
|
.
|
|
|
|
|
|
%%================================
|
|
%% ContractV1
|
|
%%================================
|
|
enc_ContractV1(Val) ->
|
|
enc_ContractV1(Val, [<<48>>]).
|
|
|
|
enc_ContractV1(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = 'enc_ContractV1_typeInfo'(Cindex2, [<<161>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractV1_typeInfo
|
|
%%================================
|
|
enc_ContractV1_typeInfo(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_ContractV1_typeInfo_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_ContractV1_typeInfo_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_ContractV1_typeInfo_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_TypeInfoV1'(H, [<<48>>]),
|
|
'enc_ContractV1_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_ContractV1(Tlv) ->
|
|
dec_ContractV1(Tlv, [16]).
|
|
|
|
dec_ContractV1(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_octet_string(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = 'dec_ContractV1_typeInfo'(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = decode_octet_string(V3, [131074]),
|
|
|
|
case Tlv4 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'ContractV1',Term1,Term2,Term3},
|
|
Res1.
|
|
'dec_ContractV1_typeInfo'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_TypeInfoV1'(V1, [16]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractV2
|
|
%%================================
|
|
enc_ContractV2(Val) ->
|
|
enc_ContractV2(Val, [<<48>>]).
|
|
|
|
enc_ContractV2(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3,Cindex4} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = 'enc_ContractV2_typeInfo'(Cindex2, [<<161>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute compilerVersion(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractV2_typeInfo
|
|
%%================================
|
|
enc_ContractV2_typeInfo(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_ContractV2_typeInfo_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_ContractV2_typeInfo_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_ContractV2_typeInfo_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_TypeInfoV1'(H, [<<48>>]),
|
|
'enc_ContractV2_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_ContractV2(Tlv) ->
|
|
dec_ContractV2(Tlv, [16]).
|
|
|
|
dec_ContractV2(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_octet_string(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = 'dec_ContractV2_typeInfo'(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = decode_octet_string(V3, [131074]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute compilerVersion(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V4|Tlv5] = Tlv4,
|
|
Term4 = decode_octet_string(V4, [131075]),
|
|
|
|
case Tlv5 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'ContractV2',Term1,Term2,Term3,Term4},
|
|
Res1.
|
|
'dec_ContractV2_typeInfo'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_TypeInfoV1'(V1, [16]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractV3
|
|
%%================================
|
|
enc_ContractV3(Val) ->
|
|
enc_ContractV3(Val, [<<48>>]).
|
|
|
|
enc_ContractV3(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3,Cindex4,Cindex5} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = 'enc_ContractV3_typeInfo'(Cindex2, [<<161>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute compilerVersion(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute payable(5) with type BOOLEAN
|
|
%%-------------------------------------------------
|
|
{EncBytes5,EncLen5} = encode_boolean(Cindex5, [<<132>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
|
|
%%================================
|
|
%% ContractV3_typeInfo
|
|
%%================================
|
|
enc_ContractV3_typeInfo(Val, TagIn) ->
|
|
{EncBytes,EncLen} = 'enc_ContractV3_typeInfo_components'(Val,[],0),
|
|
encode_tags(TagIn, EncBytes, EncLen).
|
|
|
|
'enc_ContractV3_typeInfo_components'([], AccBytes, AccLen) ->
|
|
{lists:reverse(AccBytes),AccLen};
|
|
|
|
'enc_ContractV3_typeInfo_components'([H|T],AccBytes, AccLen) ->
|
|
{EncBytes,EncLen} = 'enc_TypeInfoV3'(H, [<<48>>]),
|
|
'enc_ContractV3_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen).
|
|
|
|
|
|
|
|
dec_ContractV3(Tlv) ->
|
|
dec_ContractV3(Tlv, [16]).
|
|
|
|
dec_ContractV3(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute sourceHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_octet_string(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeInfo(2) with type SEQUENCE OF
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = 'dec_ContractV3_typeInfo'(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute byteCode(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = decode_octet_string(V3, [131074]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute compilerVersion(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V4|Tlv5] = Tlv4,
|
|
Term4 = decode_octet_string(V4, [131075]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute payable(5) with type BOOLEAN
|
|
%%-------------------------------------------------
|
|
[V5|Tlv6] = Tlv5,
|
|
Term5 = decode_boolean(V5, [131076]),
|
|
|
|
case Tlv6 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv6}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5},
|
|
Res1.
|
|
'dec_ContractV3_typeInfo'(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
['dec_TypeInfoV3'(V1, [16]) || V1 <- Tlv1].
|
|
|
|
|
|
|
|
|
|
%%================================
|
|
%% TypeInfoV1
|
|
%%================================
|
|
enc_TypeInfoV1(Val) ->
|
|
enc_TypeInfoV1(Val, [<<48>>]).
|
|
|
|
enc_TypeInfoV1(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3,Cindex4} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute argType(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute outType(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_TypeInfoV1(Tlv) ->
|
|
dec_TypeInfoV1(Tlv, [16]).
|
|
|
|
dec_TypeInfoV1(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_octet_string(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = decode_octet_string(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute argType(3) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = decode_octet_string(V3, [131074]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute outType(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V4|Tlv5] = Tlv4,
|
|
Term4 = decode_octet_string(V4, [131075]),
|
|
|
|
case Tlv5 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4},
|
|
Res1.
|
|
|
|
|
|
%%================================
|
|
%% TypeInfoV3
|
|
%%================================
|
|
enc_TypeInfoV3(Val) ->
|
|
enc_TypeInfoV3(Val, [<<48>>]).
|
|
|
|
enc_TypeInfoV3(Val, TagIn) ->
|
|
{_,Cindex1,Cindex2,Cindex3,Cindex4,Cindex5} = Val,
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute payable(3) with type BOOLEAN
|
|
%%-------------------------------------------------
|
|
{EncBytes3,EncLen3} = encode_boolean(Cindex3, [<<130>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute argType(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute outType(5) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
{EncBytes5,EncLen5} = encode_restricted_string(Cindex5, [<<132>>]),
|
|
|
|
BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5],
|
|
LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5,
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
|
|
dec_TypeInfoV3(Tlv) ->
|
|
dec_TypeInfoV3(Tlv, [16]).
|
|
|
|
dec_TypeInfoV3(Tlv, TagIn) ->
|
|
%%-------------------------------------------------
|
|
%% decode tag and length
|
|
%%-------------------------------------------------
|
|
Tlv1 = match_tags(Tlv, TagIn),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute typeHash(1) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V1|Tlv2] = Tlv1,
|
|
Term1 = decode_octet_string(V1, [131072]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute name(2) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V2|Tlv3] = Tlv2,
|
|
Term2 = decode_octet_string(V2, [131073]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute payable(3) with type BOOLEAN
|
|
%%-------------------------------------------------
|
|
[V3|Tlv4] = Tlv3,
|
|
Term3 = decode_boolean(V3, [131074]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute argType(4) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V4|Tlv5] = Tlv4,
|
|
Term4 = decode_octet_string(V4, [131075]),
|
|
|
|
%%-------------------------------------------------
|
|
%% attribute outType(5) with type OCTET STRING
|
|
%%-------------------------------------------------
|
|
[V5|Tlv6] = Tlv5,
|
|
Term5 = decode_octet_string(V5, [131076]),
|
|
|
|
case Tlv6 of
|
|
[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv6}}}) % extra fields not allowed
|
|
end,
|
|
Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5},
|
|
Res1.
|
|
|
|
%%%
|
|
%%% Run-time functions.
|
|
%%%
|
|
|
|
'dialyzer-suppressions'(Arg) ->
|
|
ok.
|
|
|
|
ber_decode_nif(B) ->
|
|
asn1rt_nif:decode_ber_tlv(B).
|
|
|
|
collect_parts(TlvList) ->
|
|
collect_parts(TlvList, []).
|
|
|
|
collect_parts([{_, L} | Rest], Acc) when is_list(L) ->
|
|
collect_parts(Rest, [collect_parts(L) | Acc]);
|
|
collect_parts([{3, <<Unused,Bits/binary>>} | Rest], _Acc) ->
|
|
collect_parts_bit(Rest, [Bits], Unused);
|
|
collect_parts([{_T, V} | Rest], Acc) ->
|
|
collect_parts(Rest, [V | Acc]);
|
|
collect_parts([], Acc) ->
|
|
list_to_binary(lists:reverse(Acc)).
|
|
|
|
collect_parts_bit([{3, <<Unused,Bits/binary>>} | Rest], Acc, Uacc) ->
|
|
collect_parts_bit(Rest, [Bits | Acc], Unused + Uacc);
|
|
collect_parts_bit([], Acc, Uacc) ->
|
|
list_to_binary([Uacc | lists:reverse(Acc)]).
|
|
|
|
decode_boolean(Tlv, TagIn) ->
|
|
Val = match_tags(Tlv, TagIn),
|
|
case Val of
|
|
<<0:8>> ->
|
|
false;
|
|
<<_:8>> ->
|
|
true;
|
|
_ ->
|
|
exit({error, {asn1, {decode_boolean, Val}}})
|
|
end.
|
|
|
|
decode_integer(Tlv, TagIn) ->
|
|
Bin = match_tags(Tlv, TagIn),
|
|
Len = byte_size(Bin),
|
|
<<Int:Len/signed-unit:8>> = Bin,
|
|
Int.
|
|
|
|
decode_octet_string(Tlv, TagsIn) ->
|
|
Bin = match_and_collect(Tlv, TagsIn),
|
|
binary:copy(Bin).
|
|
|
|
decode_restricted_string(Tlv, TagsIn) ->
|
|
match_and_collect(Tlv, TagsIn).
|
|
|
|
encode_boolean(true, TagIn) ->
|
|
encode_tags(TagIn, [255], 1);
|
|
encode_boolean(false, TagIn) ->
|
|
encode_tags(TagIn, [0], 1);
|
|
encode_boolean(X, _) ->
|
|
exit({error, {asn1, {encode_boolean, X}}}).
|
|
|
|
encode_integer(Val) ->
|
|
Bytes =
|
|
if
|
|
Val >= 0 ->
|
|
encode_integer_pos(Val, []);
|
|
true ->
|
|
encode_integer_neg(Val, [])
|
|
end,
|
|
{Bytes, length(Bytes)}.
|
|
|
|
encode_integer(Val, Tag) when is_integer(Val) ->
|
|
encode_tags(Tag, encode_integer(Val));
|
|
encode_integer(Val, _Tag) ->
|
|
exit({error, {asn1, {encode_integer, Val}}}).
|
|
|
|
encode_integer_neg(-1, [B1 | _T] = L) when B1 > 127 ->
|
|
L;
|
|
encode_integer_neg(N, Acc) ->
|
|
encode_integer_neg(N bsr 8, [N band 255 | Acc]).
|
|
|
|
encode_integer_pos(0, [B | _Acc] = L) when B < 128 ->
|
|
L;
|
|
encode_integer_pos(N, Acc) ->
|
|
encode_integer_pos(N bsr 8, [N band 255 | Acc]).
|
|
|
|
encode_length(L) when L =< 127 ->
|
|
{[L], 1};
|
|
encode_length(L) ->
|
|
Oct = minimum_octets(L),
|
|
Len = length(Oct),
|
|
if
|
|
Len =< 126 ->
|
|
{[128 bor Len | Oct], Len + 1};
|
|
true ->
|
|
exit({error, {asn1, too_long_length_oct, Len}})
|
|
end.
|
|
|
|
encode_restricted_string(OctetList, TagIn) when is_binary(OctetList) ->
|
|
encode_tags(TagIn, OctetList, byte_size(OctetList));
|
|
encode_restricted_string(OctetList, TagIn) when is_list(OctetList) ->
|
|
encode_tags(TagIn, OctetList, length(OctetList)).
|
|
|
|
encode_tags(TagIn, {BytesSoFar, LenSoFar}) ->
|
|
encode_tags(TagIn, BytesSoFar, LenSoFar).
|
|
|
|
encode_tags([Tag | Trest], BytesSoFar, LenSoFar) ->
|
|
{Bytes2, L2} = encode_length(LenSoFar),
|
|
encode_tags(Trest,
|
|
[Tag, Bytes2 | BytesSoFar],
|
|
LenSoFar + byte_size(Tag) + L2);
|
|
encode_tags([], BytesSoFar, LenSoFar) ->
|
|
{BytesSoFar, LenSoFar}.
|
|
|
|
match_and_collect(Tlv, TagsIn) ->
|
|
Val = match_tags(Tlv, TagsIn),
|
|
case Val of
|
|
[_ | _] = PartList ->
|
|
collect_parts(PartList);
|
|
Bin when is_binary(Bin) ->
|
|
Bin
|
|
end.
|
|
|
|
match_tags({T, V}, [T]) ->
|
|
V;
|
|
match_tags({T, V}, [T | Tt]) ->
|
|
match_tags(V, Tt);
|
|
match_tags([{T, V}], [T | Tt]) ->
|
|
match_tags(V, Tt);
|
|
match_tags([{T, _V} | _] = Vlist, [T]) ->
|
|
Vlist;
|
|
match_tags(Tlv, []) ->
|
|
Tlv;
|
|
match_tags({Tag, _V} = Tlv, [T | _Tt]) ->
|
|
exit({error, {asn1, {wrong_tag, {{expected, T}, {got, Tag, Tlv}}}}}).
|
|
|
|
minimum_octets(0, Acc) ->
|
|
Acc;
|
|
minimum_octets(Val, Acc) ->
|
|
minimum_octets(Val bsr 8, [Val band 255 | Acc]).
|
|
|
|
minimum_octets(Val) ->
|
|
minimum_octets(Val, []).
|