1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(asn1rtt_ext).
22-export([transform_to_EXTERNAL1990/1,transform_to_EXTERNAL1990_maps/1,
23         transform_to_EXTERNAL1994/1,transform_to_EXTERNAL1994_maps/1]).
24
25transform_to_EXTERNAL1990({_,_,_,_}=Val) ->
26    transform_to_EXTERNAL1990(tuple_to_list(Val), []);
27transform_to_EXTERNAL1990(Val) when is_tuple(Val) ->
28    %% Data already in ASN1 1990 format
29    Val.
30
31transform_to_EXTERNAL1990(['EXTERNAL'|Rest], Acc) ->
32    transform_to_EXTERNAL1990(Rest, ['EXTERNAL'|Acc]);
33transform_to_EXTERNAL1990([{syntax,Syntax}|Rest], Acc) ->
34    transform_to_EXTERNAL1990(Rest, [asn1_NOVALUE,Syntax|Acc]);
35transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest], Acc) ->
36    transform_to_EXTERNAL1990(Rest, [PCid,asn1_NOVALUE|Acc]);
37transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest], Acc) ->
38    {_,Presentation_Cid,Transfer_syntax} = Context_negot,
39    transform_to_EXTERNAL1990(Rest, [Presentation_Cid,Transfer_syntax|Acc]);
40transform_to_EXTERNAL1990([asn1_NOVALUE|Rest], Acc) ->
41    transform_to_EXTERNAL1990(Rest, [asn1_NOVALUE|Acc]);
42transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc)
43    when is_list(Data_value); is_binary(Data_value) ->
44    list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
45				 Data_val_desc|Acc]));
46transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc)
47  when is_binary(Data_value) ->
48    list_to_tuple(lists:reverse([{'single-ASN1-type',Data_value},
49				 Data_val_desc|Acc]));
50transform_to_EXTERNAL1990([Data_value], Acc)
51  when is_list(Data_value); is_binary(Data_value) ->
52    list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
53
54
55transform_to_EXTERNAL1990_maps(#{identification:=Id,'data-value':=Value}=V) ->
56    M0 = case Id of
57             {syntax,DRef} ->
58                 #{'direct-reference'=>DRef};
59             {'presentation-context-id',IndRef} ->
60                 #{'indirect-reference'=>IndRef};
61             {'context-negotiation',
62              #{'presentation-context-id':=IndRef,
63                'transfer-syntax':=DRef}} ->
64                 #{'direct-reference'=>DRef,
65                   'indirect-reference'=>IndRef}
66         end,
67    M = case V of
68            #{'data-value-descriptor':=Dvd} ->
69                M0#{'data-value-descriptor'=>Dvd};
70            #{} ->
71                M0
72        end,
73    M#{encoding=>{'octet-aligned',Value}};
74transform_to_EXTERNAL1990_maps(#{encoding:=_}=V) ->
75    %% Already in the EXTERNAL 1990 format.
76    V.
77
78
79transform_to_EXTERNAL1994({'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}=V) ->
80    Identification =
81	case {DRef,IndRef} of
82	    {DRef,asn1_NOVALUE} ->
83		{syntax,DRef};
84	    {asn1_NOVALUE,IndRef} ->
85		{'presentation-context-id',IndRef};
86	     _ ->
87		{'context-negotiation',
88		 {'EXTERNAL_identification_context-negotiation',IndRef,DRef}}
89	end,
90    case Encoding of
91	{'octet-aligned',Val} when is_list(Val); is_binary(Val) ->
92	    %% Transform to the EXTERNAL 1994 definition.
93	    {'EXTERNAL',Identification,Data_v_desc,Val};
94	_  ->
95	    %% Keep the EXTERNAL 1990 definition to avoid losing
96	    %% information.
97	    V
98    end.
99
100transform_to_EXTERNAL1994_maps(V0) ->
101    Identification =
102        case V0 of
103            #{'direct-reference':=DRef,
104              'indirect-reference':=asn1_NOVALUE} ->
105		{syntax,DRef};
106            #{'direct-reference':=asn1_NOVALUE,
107              'indirect-reference':=IndRef} ->
108		{'presentation-context-id',IndRef};
109            #{'direct-reference':=DRef,
110              'indirect-reference':=IndRef} ->
111		{'context-negotiation',
112                 #{'transfer-syntax'=>DRef,
113                   'presentation-context-id'=>IndRef}}
114	end,
115    case V0 of
116        #{encoding:={'octet-aligned',Val}}
117          when is_list(Val); is_binary(Val) ->
118	    %% Transform to the EXTERNAL 1994 definition.
119            V = #{identification=>Identification,
120                  'data-value'=>Val},
121            case V0 of
122                #{'data-value-descriptor':=asn1_NOVALUE} ->
123                    V;
124                #{'data-value-descriptor':=Dvd} ->
125                    V#{'data-value-descriptor'=>Dvd}
126            end;
127	_  ->
128	    %% Keep the EXTERNAL 1990 definition to avoid losing
129	    %% information.
130	    V = [{K,V} || {K,V} <- maps:to_list(V0),
131                          V =/= asn1_NOVALUE],
132            maps:from_list(V)
133    end.
134