When performance is of highest priority and you are interested in a limited part of the ASN.1 encoded message before deciding what to do with the rest of it, an option is to decode only this small part. The situation can be a server that has to decide the addressee of a message. The addressee can be interested in the entire message, but the server can be a bottleneck that you want to spare any unnecessary load.
Instead of making two complete decodes (the normal case of decode), one in the server and one in the addressee, it is only necessary to make one specialized decode(in the server) and another complete decode(in the addressee). This section describes the following two specialized decodes, which support to solve this and similar problems:
This functionality is only provided when using 
The basic idea with exclusive
      decode is to specify which parts of the message you want to
      exclude from being decoded. These parts remain encoded and are
      returned in the value structure as binaries. They can be decoded
      in turn by passing them to a certain 
To perform an exclusive decode:
Step 2: Include the following instructions in a configuration file:
The runtime user interface for exclusive decode consists of the following two functions:
Both functions are described in the following.
If the exclusive decode function has, for example, the name
        
{ok,Excl_Message} = 'MyModule':decode_exclusive(Bin)      
      The result 
Each undecoded part that is to be decoded must be fed into
        function 
{ok,Part_Message} = 'MyModule':decode_part(Type_Key,Undecoded_Value)
    This instruction is written in the configuration file in the following format:
Exclusive_Decode_Instruction = {exclusive_decode,{Module_Name,Decode_Instructions}}.
Module_Name = atom()
Decode_Instructions = [Decode_Instruction]+
Decode_Instruction = {Exclusive_Decode_Function_Name,Type_List}
Exclusive_Decode_Function_Name = atom()
Type_List = [Top_Type,Element_List]
Element_List = [Element]+
Element = {Name,parts} |
          {Name,undecoded} |
          {Name,Element_List}
Top_Type = atom()
Name = atom()
      The instruction must be a valid Erlang term ended by a dot.
In 
The use and effect of the actions are as follows:
In this examples, the definitions from the following ASN.1 specification are used:
If 
Another top type is 
The following figure shows the bytes of a 
Compiling 
unix> erlc -bber +asn1config GUI.asn
erlang> asn1ct:compile('GUI', [ber,asn1config]).
      The module can be used as follows:
1> Button_Msg = {'Button',123,true}.
{'Button',123,true}
2> {ok,Button_Bytes} = 'GUI':encode('Button',Button_Msg).
{ok,[<<48>>,
     [6],
     [<<128>>,
      [1],
      123],
     [<<129>>,
      [1],
      255]]}
3> {ok,Exclusive_Msg_Button} = 'GUI':decode_Button_exclusive(list_to_binary(Button_Bytes)).
{ok,{'Button',{'Button_number',<<28,1,123>>},
         true}}
4> 'GUI':decode_part('Button_number',<<128,1,123>>).
{ok,123}
5> Window_Msg = 
{'Window',{status,{'Status',35,
              [{'Button',3,true},
               {'Button',4,false},
               {'Button',5,true},
               {'Button',6,true},
               {'Button',7,false},
               {'Button',8,true},
               {'Button',9,true},
               {'Button',10,false},
               {'Button',11,true},
               {'Button',12,true},
               {'Button',13,false},
               {'Button',14,true}],
              false,
              {possibleActions,[{'Action',16,{'Button',17,true}}]}}}}. 
{'Window',{status,{'Status',35,
              [{'Button',3,true},
               {'Button',4,false},
               {'Button',5,true},
               {'Button',6,true},
               {'Button',7,false},
               {'Button',8,true},
               {'Button',9,true},
               {'Button',10,false},
               {'Button',11,true},
               {'Button',12,true},
               {'Button',13,false},
               {'Button',14,true}],
              false,
              {possibleActions,[{'Action',16,{'Button',17,true}}]}}}}
6> {ok,Window_Bytes}='GUI':encode('Window',Window_Msg).
{ok,[<<161>>,
     [127],
     [<<128>>, ...
8> {ok,{status,{'Status',Int,{Type_Key_SeqOf,Val_SEQOF},
BoolOpt,{Type_Key_Choice,Val_Choice}}}}=
'GUI':decode_Window_status_exclusive(list_to_binary(Window_Bytes)).
{ok,{status,{'Status',35,
        {'Status_buttonList',[<<48,6,128,1,3,129,1,255>>,
                              <<48,6,128,1,4,129,1,0>>,
                              <<48,6,128,1,5,129,1,255>>,
                              <<48,6,128,1,6,129,1,255>>,
                              <<48,6,128,1,7,129,1,0>>,
                              <<48,6,128,1,8,129,1,255>>,
                              <<48,6,128,1,9,129,1,255>>,
                              <<48,6,128,1,10,129,1,0>>,
                              <<48,6,128,1,11,129,1,255>>,
                              <<48,6,128,1,12,129,1,255>>,
                              <<48,6,128,1,13,129,1,0>>,
                              <<48,6,128,1,14,129,1,255>>]},
        false,
        {'Status_actions',
<<163,21,160,19,48,17,2,1,16,160,12,172,10,171,8,48,6,128,1,...>>}}}}
10> 'GUI':decode_part(Type_Key_SeqOf,Val_SEQOF).
{ok,[{'Button',3,true},
     {'Button',4,false},
     {'Button',5,true},
     {'Button',6,true},
     {'Button',7,false},
     {'Button',8,true},
     {'Button',9,true},
     {'Button',10,false},
     {'Button',11,true},
     {'Button',12,true},
     {'Button',13,false},
     {'Button',14,true}]}
11> 'GUI':decode_part(Type_Key_SeqOf,hd(Val_SEQOF)).
{ok,{'Button',3,true}}
12> 'GUI':decode_part(Type_Key_Choice,Val_Choice).  
{ok,{possibleActions,[{'Action',16,{'Button',17,true}}]}}
    This specialized decode decodes a subtype of a
      constructed value and is the fastest method to extract a
      subvalue. This decode is typically used when you want to
      inspect, for example, a version number, to be able to decide what
      to do with the entire value. The result is returned as
      
To perform a selective decode:
Step 1: Include the following instructions in the configuration file:
The only new user interface function is the one provided by the
        user in the configuration file. The function is started by
        the 
For example, if the configuration file includes the specification
        
One or more selective decode functions can be described in a configuration file. Use the following notation:
Selective_Decode_Instruction = {selective_decode,{Module_Name,Decode_Instructions}}.
Module_Name = atom()
Decode_Instructions = [Decode_Instruction]+
Decode_Instruction = {Selective_Decode_Function_Name,Type_List}
Selective_Decode_Function_Name = atom()
Type_List = [Top_Type|Element_List]
Element_List = Name|List_Selector
Name = atom()
List_Selector = [integer()]
      The instruction must be a valid Erlang term ended by a dot.
In the example, component 
In this example, the same ASN.1 specification as in Section
        
{selective_decode,
    {'GUI',
        [{selected_decode_Window1,
            ['Window',status,buttonList, 
             [1],
             number]},
 {selected_decode_Action,
     ['Action',handle,number]},
 {selected_decode_Window2,
     ['Window',
      status,
      actions,
      possibleActions,
      [1],
      handle,number]}]}}.
      The first instruction,
        
 The second instruction,
        
ValAction = {'Action',17,{'Button',4711,false}}.
{'Action',17,{'Button',4711,false}}
7> {ok,Bytes}='GUI':encode('Action',ValAction).
...
8> BinBytes = list_to_binary(Bytes).
<<48,18,2,1,17,160,13,172,11,171,9,48,7,128,2,18,103,129,1,0>>
9> 'GUI':selected_decode_Action(BinBytes).
{ok,4711}
10>
      The third instruction,
        
The following figure shows which components are in 
In the following figure, only the marked element is decoded by
        
With the following example, you can examine that both
        
1> Val = {'Window',{status,{'Status',12,
                    [{'Button',13,true},
                     {'Button',14,false},
                     {'Button',15,true},
                     {'Button',16,false}],
                    true,
                    {possibleActions,[{'Action',17,{'Button',18,false}},
                                      {'Action',19,{'Button',20,true}},
                                      {'Action',21,{'Button',22,false}}]}}}}
2> {ok,Bytes}='GUI':encode('Window',Val).
...
3> Bin = list_to_binary(Bytes).
<<161,101,128,1,12,161,32,48,6,128,1,13,129,1,255,48,6,128,1,14,129,1,0,48,6,128,1,15,129,...>>
4> 'GUI':selected_decode_Window1(Bin).
{ok,13}
5> 'GUI':selected_decode_Window2(Bin).
{ok,18}
      Notice that the value fed into the selective decode functions must be a binary.
To give an indication on the possible performance gain using the specialized decodes, some measures have been performed. The relative figures in the outcome between selective, exclusive, and complete decode (the normal case) depend on the structure of the type, the size of the message, and on what level the selective and exclusive decodes are specified.
The specifications 
For the 
{selective_decode,
  {'GUI',
    [{selected_decode_Window1,
         ['Window',
          status,buttonList,
          [1],
          number]},
     {selected_decode_Window2,
         ['Window',
          status,
          actions,
          possibleActions,
          [1],
          handle,number]}]}}.
     {exclusive_decode,
         {'GUI',
            [{decode_Window_status_exclusive,
                ['Window',
                 [{status,
                     [{buttonList,parts},
                      {actions,undecoded}]}]]}]}}.
      The 
{exclusive_decode,
  {'MEDIA-GATEWAY-CONTROL',
    [{decode_MegacoMessage_exclusive,
        ['MegacoMessage',
         [{authHeader,undecoded},
          {mess,
             [{mId,undecoded},
              {messageBody,undecoded}]}]]}]}}.
{selective_decode,
  {'MEDIA-GATEWAY-CONTROL',
    [{decode_MegacoMessage_selective,
         ['MegacoMessage',mess,version]}]}}.
      The corresponding values were as follows:
{'Window',{status,{'Status',12,
              [{'Button',13,true},
               {'Button',14,false},
               {'Button',15,true},
               {'Button',16,false},
               {'Button',13,true},
               {'Button',14,false},
               {'Button',15,true},
               {'Button',16,false},
               {'Button',13,true},
               {'Button',14,false},
               {'Button',15,true},
               {'Button',16,false}],
              true,
              {possibleActions,
                 [{'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}},
                  {'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}},
                  {'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}},
                  {'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}},
                  {'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}},
                  {'Action',17,{'Button',18,false}},
                  {'Action',19,{'Button',20,true}},
                  {'Action',21,{'Button',22,false}}]}}}}
{'MegacoMessage',asn1_NOVALUE,
  {'Message',1,
    {ip4Address,
      {'IP4Address',[125,125,125,111],55555}},
  {transactions,
    [{transactionReply,
      {'TransactionReply',50007,asn1_NOVALUE,
       {actionReplies,
        [{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
          [{auditValueReply,{auditResult,{'AuditResult',
            {'TerminationID',[],[255,255,255]},
             [{mediaDescriptor,
               {'MediaDescriptor',asn1_NOVALUE,
                {multiStream,
                 [{'StreamDescriptor',1,
                   {'StreamParms',
                    {'LocalControlDescriptor',
                     sendRecv,
                     asn1_NOVALUE,
                     asn1_NOVALUE,
                     [{'PropertyParm',
                       [0,11,0,7],
                       [[52,48]],
                       asn1_NOVALUE}]},
                    {'LocalRemoteDescriptor',
                     [[{'PropertyParm',
                        [0,0,176,1],
                        [[48]],
                        asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,8],
                         [[73,78,32,73,80,52,32,49,50,53,46,49,
                           50,53,46,49,50,53,46,49,49,49]],
                         asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,15],
                         [[97,117,100,105,111,32,49,49,49,49,32,
                           82,84,80,47,65,86,80,32,32,52]],
                         asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,12],
                         [[112,116,105,109,101,58,51,48]],
                         asn1_NOVALUE}]]},
                    {'LocalRemoteDescriptor',
                     [[{'PropertyParm',
                         [0,0,176,1],
                         [[48]],
                         asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,8],
                         [[73,78,32,73,80,52,32,49,50,52,46,49,50,
                           52,46,49,50,52,46,50,50,50]],
                         asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,15],
                         [[97,117,100,105,111,32,50,50,50,50,32,82,
                           84,80,47,65,86,80,32,32,52]],
                         asn1_NOVALUE},
                       {'PropertyParm',
                         [0,0,176,12],
                         [[112,116,105,109,101,58,51,48]],
                         asn1_NOVALUE}]]}}}]}}},
              {packagesDescriptor,
               [{'PackagesItem',[0,11],1},
                {'PackagesItem',[0,11],1}]},
              {statisticsDescriptor,
               [{'StatisticsParameter',[0,12,0,4],[[49,50,48,48]]},
                {'StatisticsParameter',[0,11,0,2],[[54,50,51,48,48]]},
                {'StatisticsParameter',[0,12,0,5],[[55,48,48]]},
                {'StatisticsParameter',[0,11,0,3],[[52,53,49,48,48]]},
                {'StatisticsParameter',[0,12,0,6],[[48,46,50]]},
                {'StatisticsParameter',[0,12,0,7],[[50,48]]},
                {'StatisticsParameter',[0,12,0,8],[[52,48]]}]}]}}}]}]}}}]}}}
      The size of the encoded values was 458 bytes for 
The ASN.1 specifications in the test were compiled with options
        
The test program runs 10000 decodes on the value, resulting in an output with the elapsed time in microseconds for the total number of decodes.
It is also of interest to know the relation is between
        a complete decode, an exclusive decode followed by
        
Other ASN.1 types and values can differ much from these figures. It is therefore important that you, in every case where you intend to use either of these decodes, perform some tests that show if you will benefit your purpose.