File: //usr/local/CyberCP/lib64/python3.10/site-packages/pyasn1/type/base.py
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
from pyasn1 import error
from pyasn1.compat import calling
from pyasn1.type import constraint
from pyasn1.type import tag
from pyasn1.type import tagmap
__all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type',
           'ConstructedAsn1Type']
class Asn1Item(object):
    @classmethod
    def getTypeId(cls, increment=1):
        try:
            Asn1Item._typeCounter += increment
        except AttributeError:
            Asn1Item._typeCounter = increment
        return Asn1Item._typeCounter
class Asn1Type(Asn1Item):
    """Base class for all classes representing ASN.1 types.
    In the user code, |ASN.1| class is normally used only for telling
    ASN.1 objects from others.
    Note
    ----
    For as long as ASN.1 is concerned, a way to compare ASN.1 types
    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
    """
    #: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing
    #: ASN.1 tag(s) associated with |ASN.1| type.
    tagSet = tag.TagSet()
    #: Default :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
    #: object imposing constraints on initialization values.
    subtypeSpec = constraint.ConstraintsIntersection()
    # Disambiguation ASN.1 types identification
    typeId = None
    def __init__(self, **kwargs):
        readOnly = {
            'tagSet': self.tagSet,
            'subtypeSpec': self.subtypeSpec
        }
        readOnly.update(kwargs)
        self.__dict__.update(readOnly)
        self._readOnly = readOnly
    def __setattr__(self, name, value):
        if name[0] != '_' and name in self._readOnly:
            raise error.PyAsn1Error('read-only instance attribute "%s"' % name)
        self.__dict__[name] = value
    def __str__(self):
        return self.prettyPrint()
    @property
    def readOnly(self):
        return self._readOnly
    @property
    def effectiveTagSet(self):
        """For |ASN.1| type is equivalent to *tagSet*
        """
        return self.tagSet  # used by untagged types
    @property
    def tagMap(self):
        """Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects within callee object.
        """
        return tagmap.TagMap({self.tagSet: self})
    def isSameTypeWith(self, other, matchTags=True, matchConstraints=True):
        """Examine |ASN.1| type for equality with other ASN.1 type.
        ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
        (:py:mod:`~pyasn1.type.constraint`) are examined when carrying
        out ASN.1 types comparison.
        Python class inheritance relationship is NOT considered.
        Parameters
        ----------
        other: a pyasn1 type object
            Class instance representing ASN.1 type.
        Returns
        -------
        : :class:`bool`
            :obj:`True` if *other* is |ASN.1| type,
            :obj:`False` otherwise.
        """
        return (self is other or
                (not matchTags or self.tagSet == other.tagSet) and
                (not matchConstraints or self.subtypeSpec == other.subtypeSpec))
    def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
        """Examine |ASN.1| type for subtype relationship with other ASN.1 type.
        ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
        (:py:mod:`~pyasn1.type.constraint`) are examined when carrying
        out ASN.1 types comparison.
        Python class inheritance relationship is NOT considered.
        Parameters
        ----------
            other: a pyasn1 type object
                Class instance representing ASN.1 type.
        Returns
        -------
            : :class:`bool`
                :obj:`True` if *other* is a subtype of |ASN.1| type,
                :obj:`False` otherwise.
        """
        return (not matchTags or
                (self.tagSet.isSuperTagSetOf(other.tagSet)) and
                 (not matchConstraints or self.subtypeSpec.isSuperTypeOf(other.subtypeSpec)))
    @staticmethod
    def isNoValue(*values):
        for value in values:
            if value is not noValue:
                return False
        return True
    def prettyPrint(self, scope=0):
        raise NotImplementedError()
    # backward compatibility
    def getTagSet(self):
        return self.tagSet
    def getEffectiveTagSet(self):
        return self.effectiveTagSet
    def getTagMap(self):
        return self.tagMap
    def getSubtypeSpec(self):
        return self.subtypeSpec
    # backward compatibility
    def hasValue(self):
        return self.isValue
# Backward compatibility
Asn1ItemBase = Asn1Type
class NoValue(object):
    """Create a singleton instance of NoValue class.
    The *NoValue* sentinel object represents an instance of ASN.1 schema
    object as opposed to ASN.1 value object.
    Only ASN.1 schema-related operations can be performed on ASN.1
    schema objects.
    Warning
    -------
    Any operation attempted on the *noValue* object will raise the
    *PyAsn1Error* exception.
    """
    skipMethods = set(
        ('__slots__',
         # attributes
         '__getattribute__',
         '__getattr__',
         '__setattr__',
         '__delattr__',
         # class instance
         '__class__',
         '__init__',
         '__del__',
         '__new__',
         '__repr__',
         '__qualname__',
         '__objclass__',
         'im_class',
         '__sizeof__',
         # pickle protocol
         '__reduce__',
         '__reduce_ex__',
         '__getnewargs__',
         '__getinitargs__',
         '__getstate__',
         '__setstate__')
    )
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            def getPlug(name):
                def plug(self, *args, **kw):
                    raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name)
                return plug
            op_names = [name
                        for typ in (str, int, list, dict)
                        for name in dir(typ)
                        if (name not in cls.skipMethods and
                            name.startswith('__') and
                            name.endswith('__') and
                            calling.callable(getattr(typ, name)))]
            for name in set(op_names):
                setattr(cls, name, getPlug(name))
            cls._instance = object.__new__(cls)
        return cls._instance
    def __getattr__(self, attr):
        if attr in self.skipMethods:
            raise AttributeError('Attribute %s not present' % attr)
        raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr)
    def __repr__(self):
        return '<%s object>' % self.__class__.__name__
noValue = NoValue()
class SimpleAsn1Type(Asn1Type):
    """Base class for all simple classes representing ASN.1 types.
    ASN.1 distinguishes types by their ability to hold other objects.
    Scalar types are known as *simple* in ASN.1.
    In the user code, |ASN.1| class is normally used only for telling
    ASN.1 objects from others.
    Note
    ----
    For as long as ASN.1 is concerned, a way to compare ASN.1 types
    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
    """
    #: Default payload value
    defaultValue = noValue
    def __init__(self, value=noValue, **kwargs):
        Asn1Type.__init__(self, **kwargs)
        if value is noValue:
            value = self.defaultValue
        else:
            value = self.prettyIn(value)
            try:
                self.subtypeSpec(value)
            except error.PyAsn1Error:
                exType, exValue, exTb = sys.exc_info()
                raise exType('%s at %s' % (exValue, self.__class__.__name__))
        self._value = value
    def __repr__(self):
        representation = '%s %s object' % (
            self.__class__.__name__, self.isValue and 'value' or 'schema')
        for attr, value in self.readOnly.items():
            if value:
                representation += ', %s %s' % (attr, value)
        if self.isValue:
            value = self.prettyPrint()
            if len(value) > 32:
                value = value[:16] + '...' + value[-16:]
            representation += ', payload [%s]' % value
        return '<%s>' % representation
    def __eq__(self, other):
        return self is other and True or self._value == other
    def __ne__(self, other):
        return self._value != other
    def __lt__(self, other):
        return self._value < other
    def __le__(self, other):
        return self._value <= other
    def __gt__(self, other):
        return self._value > other
    def __ge__(self, other):
        return self._value >= other
    if sys.version_info[0] <= 2:
        def __nonzero__(self):
            return self._value and True or False
    else:
        def __bool__(self):
            return self._value and True or False
    def __hash__(self):
        return hash(self._value)
    @property
    def isValue(self):
        """Indicate that |ASN.1| object represents ASN.1 value.
        If *isValue* is :obj:`False` then this object represents just
        ASN.1 schema.
        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema
        features, this object can also be used like a Python built-in object
        (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
        Returns
        -------
        : :class:`bool`
            :obj:`False` if object represents just ASN.1 schema.
            :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
        Note
        ----
        There is an important distinction between PyASN1 schema and value objects.
        The PyASN1 schema objects can only participate in ASN.1 schema-related
        operations (e.g. defining or testing the structure of the data). Most
        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
        encoding/decoding serialised ASN.1 contents.
        The PyASN1 value objects can **additionally** participate in many operations
        involving regular Python objects (e.g. arithmetic, comprehension etc).
        """
        return self._value is not noValue
    def clone(self, value=noValue, **kwargs):
        """Create a modified version of |ASN.1| schema or value object.
        The `clone()` method accepts the same set arguments as |ASN.1|
        class takes on instantiation except that all arguments
        of the `clone()` method are optional.
        Whatever arguments are supplied, they are used to create a copy
        of `self` taking precedence over the ones used to instantiate `self`.
        Note
        ----
        Due to the immutable nature of the |ASN.1| object, if no arguments
        are supplied, no new |ASN.1| object will be created and `self` will
        be returned instead.
        """
        if value is noValue:
            if not kwargs:
                return self
            value = self._value
        initializers = self.readOnly.copy()
        initializers.update(kwargs)
        return self.__class__(value, **initializers)
    def subtype(self, value=noValue, **kwargs):
        """Create a specialization of |ASN.1| schema or value object.
        The subtype relationship between ASN.1 types has no correlation with
        subtype relationship between Python types. ASN.1 type is mainly identified
        by its tag(s) (:py:class:`~pyasn1.type.tag.TagSet`) and value range
        constraints (:py:class:`~pyasn1.type.constraint.ConstraintsIntersection`).
        These ASN.1 type properties are implemented as |ASN.1| attributes.  
        The `subtype()` method accepts the same set arguments as |ASN.1|
        class takes on instantiation except that all parameters
        of the `subtype()` method are optional.
        With the exception of the arguments described below, the rest of
        supplied arguments they are used to create a copy of `self` taking
        precedence over the ones used to instantiate `self`.
        The following arguments to `subtype()` create a ASN.1 subtype out of
        |ASN.1| type:
        Other Parameters
        ----------------
        implicitTag: :py:class:`~pyasn1.type.tag.Tag`
            Implicitly apply given ASN.1 tag object to `self`'s
            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
            new object's ASN.1 tag(s).
        explicitTag: :py:class:`~pyasn1.type.tag.Tag`
            Explicitly apply given ASN.1 tag object to `self`'s
            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
            new object's ASN.1 tag(s).
        subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
            Add ASN.1 constraints object to one of the `self`'s, then
            use the result as new object's ASN.1 constraints.
        Returns
        -------
        :
            new instance of |ASN.1| schema or value object
        Note
        ----
        Due to the immutable nature of the |ASN.1| object, if no arguments
        are supplied, no new |ASN.1| object will be created and `self` will
        be returned instead.
        """
        if value is noValue:
            if not kwargs:
                return self
            value = self._value
        initializers = self.readOnly.copy()
        implicitTag = kwargs.pop('implicitTag', None)
        if implicitTag is not None:
            initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
        explicitTag = kwargs.pop('explicitTag', None)
        if explicitTag is not None:
            initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
        for arg, option in kwargs.items():
            initializers[arg] += option
        return self.__class__(value, **initializers)
    def prettyIn(self, value):
        return value
    def prettyOut(self, value):
        return str(value)
    def prettyPrint(self, scope=0):
        return self.prettyOut(self._value)
    def prettyPrintType(self, scope=0):
        return '%s -> %s' % (self.tagSet, self.__class__.__name__)
# Backward compatibility
AbstractSimpleAsn1Item = SimpleAsn1Type
#
# Constructed types:
# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
# * ASN1 types and values are represened by Python class instances
# * Value initialization is made for defaulted components only
# * Primary method of component addressing is by-position. Data model for base
#   type is Python sequence. Additional type-specific addressing methods
#   may be implemented for particular types.
# * SequenceOf and SetOf types do not implement any additional methods
# * Sequence, Set and Choice types also implement by-identifier addressing
# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing
# * Sequence and Set types may include optional and defaulted
#   components
# * Constructed types hold a reference to component types used for value
#   verification and ordering.
# * Component type is a scalar type for SequenceOf/SetOf types and a list
#   of types for Sequence/Set/Choice.
#
class ConstructedAsn1Type(Asn1Type):
    """Base class for all constructed classes representing ASN.1 types.
    ASN.1 distinguishes types by their ability to hold other objects.
    Those "nesting" types are known as *constructed* in ASN.1.
    In the user code, |ASN.1| class is normally used only for telling
    ASN.1 objects from others.
    Note
    ----
    For as long as ASN.1 is concerned, a way to compare ASN.1 types
    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
    """
    #: If :obj:`True`, requires exact component type matching,
    #: otherwise subtype relation is only enforced
    strictConstraints = False
    componentType = None
    # backward compatibility, unused
    sizeSpec = constraint.ConstraintsIntersection()
    def __init__(self, **kwargs):
        readOnly = {
            'componentType': self.componentType,
            # backward compatibility, unused
            'sizeSpec': self.sizeSpec
        }
        # backward compatibility: preserve legacy sizeSpec support
        kwargs = self._moveSizeSpec(**kwargs)
        readOnly.update(kwargs)
        Asn1Type.__init__(self, **readOnly)
    def _moveSizeSpec(self, **kwargs):
        # backward compatibility, unused
        sizeSpec = kwargs.pop('sizeSpec', self.sizeSpec)
        if sizeSpec:
            subtypeSpec = kwargs.pop('subtypeSpec', self.subtypeSpec)
            if subtypeSpec:
                subtypeSpec = sizeSpec
            else:
                subtypeSpec += sizeSpec
            kwargs['subtypeSpec'] = subtypeSpec
        return kwargs
    def __repr__(self):
        representation = '%s %s object' % (
            self.__class__.__name__, self.isValue and 'value' or 'schema'
        )
        for attr, value in self.readOnly.items():
            if value is not noValue:
                representation += ', %s=%r' % (attr, value)
        if self.isValue and self.components:
            representation += ', payload [%s]' % ', '.join(
                [repr(x) for x in self.components])
        return '<%s>' % representation
    def __eq__(self, other):
        return self is other or self.components == other
    def __ne__(self, other):
        return self.components != other
    def __lt__(self, other):
        return self.components < other
    def __le__(self, other):
        return self.components <= other
    def __gt__(self, other):
        return self.components > other
    def __ge__(self, other):
        return self.components >= other
    if sys.version_info[0] <= 2:
        def __nonzero__(self):
            return bool(self.components)
    else:
        def __bool__(self):
            return bool(self.components)
    @property
    def components(self):
        raise error.PyAsn1Error('Method not implemented')
    def _cloneComponentValues(self, myClone, cloneValueFlag):
        pass
    def clone(self, **kwargs):
        """Create a modified version of |ASN.1| schema object.
        The `clone()` method accepts the same set arguments as |ASN.1|
        class takes on instantiation except that all arguments
        of the `clone()` method are optional.
        Whatever arguments are supplied, they are used to create a copy
        of `self` taking precedence over the ones used to instantiate `self`.
        Possible values of `self` are never copied over thus `clone()` can
        only create a new schema object.
        Returns
        -------
        :
            new instance of |ASN.1| type/value
        Note
        ----
        Due to the mutable nature of the |ASN.1| object, even if no arguments
        are supplied, a new |ASN.1| object will be created and returned.
        """
        cloneValueFlag = kwargs.pop('cloneValueFlag', False)
        initializers = self.readOnly.copy()
        initializers.update(kwargs)
        clone = self.__class__(**initializers)
        if cloneValueFlag:
            self._cloneComponentValues(clone, cloneValueFlag)
        return clone
    def subtype(self, **kwargs):
        """Create a specialization of |ASN.1| schema object.
        The `subtype()` method accepts the same set arguments as |ASN.1|
        class takes on instantiation except that all parameters
        of the `subtype()` method are optional.
        With the exception of the arguments described below, the rest of
        supplied arguments they are used to create a copy of `self` taking
        precedence over the ones used to instantiate `self`.
        The following arguments to `subtype()` create a ASN.1 subtype out of
        |ASN.1| type.
        Other Parameters
        ----------------
        implicitTag: :py:class:`~pyasn1.type.tag.Tag`
            Implicitly apply given ASN.1 tag object to `self`'s
            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
            new object's ASN.1 tag(s).
        explicitTag: :py:class:`~pyasn1.type.tag.Tag`
            Explicitly apply given ASN.1 tag object to `self`'s
            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
            new object's ASN.1 tag(s).
        subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
            Add ASN.1 constraints object to one of the `self`'s, then
            use the result as new object's ASN.1 constraints.
        Returns
        -------
        :
            new instance of |ASN.1| type/value
        Note
        ----
        Due to the mutable nature of the |ASN.1| object, even if no arguments
        are supplied, a new |ASN.1| object will be created and returned.
        """
        initializers = self.readOnly.copy()
        cloneValueFlag = kwargs.pop('cloneValueFlag', False)
        implicitTag = kwargs.pop('implicitTag', None)
        if implicitTag is not None:
            initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
        explicitTag = kwargs.pop('explicitTag', None)
        if explicitTag is not None:
            initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
        for arg, option in kwargs.items():
            initializers[arg] += option
        clone = self.__class__(**initializers)
        if cloneValueFlag:
            self._cloneComponentValues(clone, cloneValueFlag)
        return clone
    def getComponentByPosition(self, idx):
        raise error.PyAsn1Error('Method not implemented')
    def setComponentByPosition(self, idx, value, verifyConstraints=True):
        raise error.PyAsn1Error('Method not implemented')
    def setComponents(self, *args, **kwargs):
        for idx, value in enumerate(args):
            self[idx] = value
        for k in kwargs:
            self[k] = kwargs[k]
        return self
    # backward compatibility
    def setDefaultComponents(self):
        pass
    def getComponentType(self):
        return self.componentType
    # backward compatibility, unused
    def verifySizeSpec(self):
        self.subtypeSpec(self)
        # Backward compatibility
AbstractConstructedAsn1Item = ConstructedAsn1Type