1# 
    2# This file is part of pyasn1 software. 
    3# 
    4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com> 
    5# License: https://pyasn1.readthedocs.io/en/latest/license.html 
    6# 
    7import warnings 
    8 
    9from pyasn1 import error 
    10from pyasn1.codec.cer import encoder 
    11from pyasn1.type import univ 
    12 
    13__all__ = ['Encoder', 'encode'] 
    14 
    15 
    16class SetEncoder(encoder.SetEncoder): 
    17    @staticmethod 
    18    def _componentSortKey(componentAndType): 
    19        """Sort SET components by tag 
    20 
    21        Sort depending on the actual Choice value (dynamic sort) 
    22        """ 
    23        component, asn1Spec = componentAndType 
    24 
    25        if asn1Spec is None: 
    26            compType = component 
    27        else: 
    28            compType = asn1Spec 
    29 
    30        if compType.typeId == univ.Choice.typeId and not compType.tagSet: 
    31            if asn1Spec is None: 
    32                return component.getComponent().tagSet 
    33            else: 
    34                # TODO: move out of sorting key function 
    35                names = [namedType.name for namedType in asn1Spec.componentType.namedTypes 
    36                         if namedType.name in component] 
    37                if len(names) != 1: 
    38                    raise error.PyAsn1Error( 
    39                        '%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', component)) 
    40 
    41                # TODO: support nested CHOICE ordering 
    42                return asn1Spec[names[0]].tagSet 
    43 
    44        else: 
    45            return compType.tagSet 
    46 
    47 
    48TAG_MAP = encoder.TAG_MAP.copy() 
    49 
    50TAG_MAP.update({ 
    51    # Set & SetOf have same tags 
    52    univ.Set.tagSet: SetEncoder() 
    53}) 
    54 
    55TYPE_MAP = encoder.TYPE_MAP.copy() 
    56 
    57TYPE_MAP.update({ 
    58    # Set & SetOf have same tags 
    59    univ.Set.typeId: SetEncoder() 
    60}) 
    61 
    62 
    63class SingleItemEncoder(encoder.SingleItemEncoder): 
    64    fixedDefLengthMode = True 
    65    fixedChunkSize = 0 
    66 
    67    TAG_MAP = TAG_MAP 
    68    TYPE_MAP = TYPE_MAP 
    69 
    70 
    71class Encoder(encoder.Encoder): 
    72    SINGLE_ITEM_ENCODER = SingleItemEncoder 
    73 
    74 
    75#: Turns ASN.1 object into DER octet stream. 
    76#: 
    77#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) 
    78#: walks all its components recursively and produces a DER octet stream. 
    79#: 
    80#: Parameters 
    81#: ---------- 
    82#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) 
    83#:     A Python or pyasn1 object to encode. If Python object is given, `asnSpec` 
    84#:     parameter is required to guide the encoding process. 
    85#: 
    86#: Keyword Args 
    87#: ------------ 
    88#: asn1Spec: 
    89#:     Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 
    90#: 
    91#: Returns 
    92#: ------- 
    93#: : :py:class:`bytes` 
    94#:     Given ASN.1 object encoded into BER octet-stream 
    95#: 
    96#: Raises 
    97#: ------ 
    98#: ~pyasn1.error.PyAsn1Error 
    99#:     On encoding errors 
    100#: 
    101#: Examples 
    102#: -------- 
    103#: Encode Python value into DER with ASN.1 schema 
    104#: 
    105#: .. code-block:: pycon 
    106#: 
    107#:    >>> seq = SequenceOf(componentType=Integer()) 
    108#:    >>> encode([1, 2, 3], asn1Spec=seq) 
    109#:    b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' 
    110#: 
    111#: Encode ASN.1 value object into DER 
    112#: 
    113#: .. code-block:: pycon 
    114#: 
    115#:    >>> seq = SequenceOf(componentType=Integer()) 
    116#:    >>> seq.extend([1, 2, 3]) 
    117#:    >>> encode(seq) 
    118#:    b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' 
    119#: 
    120encode = Encoder() 
    121 
    122def __getattr__(attr: str): 
    123    if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr): 
    124        warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning) 
    125        return globals()[newAttr] 
    126    raise AttributeError(attr)