123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #
- # This file is part of pyasn1 software.
- #
- # Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
- # License: http://snmplabs.com/pyasn1/license.html
- #
- from pyasn1 import error
-
- __all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
- 'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
- 'tagCategoryImplicit', 'tagCategoryExplicit',
- 'tagCategoryUntagged', 'Tag', 'TagSet']
-
- #: Identifier for ASN.1 class UNIVERSAL
- tagClassUniversal = 0x00
-
- #: Identifier for ASN.1 class APPLICATION
- tagClassApplication = 0x40
-
- #: Identifier for ASN.1 class context-specific
- tagClassContext = 0x80
-
- #: Identifier for ASN.1 class private
- tagClassPrivate = 0xC0
-
- #: Identifier for "simple" ASN.1 structure (e.g. scalar)
- tagFormatSimple = 0x00
-
- #: Identifier for "constructed" ASN.1 structure (e.g. may have inner components)
- tagFormatConstructed = 0x20
-
- tagCategoryImplicit = 0x01
- tagCategoryExplicit = 0x02
- tagCategoryUntagged = 0x04
-
-
- class Tag(object):
- """Create ASN.1 tag
-
- Represents ASN.1 tag that can be attached to a ASN.1 type to make
- types distinguishable from each other.
-
- *Tag* objects are immutable and duck-type Python :class:`tuple` objects
- holding three integer components of a tag.
-
- Parameters
- ----------
- tagClass: :py:class:`int`
- Tag *class* value
-
- tagFormat: :py:class:`int`
- Tag *format* value
-
- tagId: :py:class:`int`
- Tag ID value
- """
- def __init__(self, tagClass, tagFormat, tagId):
- if tagId < 0:
- raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId)
- self.__tagClass = tagClass
- self.__tagFormat = tagFormat
- self.__tagId = tagId
- self.__tagClassId = tagClass, tagId
- self.__hash = hash(self.__tagClassId)
-
- def __repr__(self):
- representation = '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
- return '<%s object at 0x%x tag %s>' % (self.__class__.__name__, id(self), representation)
-
- def __eq__(self, other):
- return self.__tagClassId == other
-
- def __ne__(self, other):
- return self.__tagClassId != other
-
- def __lt__(self, other):
- return self.__tagClassId < other
-
- def __le__(self, other):
- return self.__tagClassId <= other
-
- def __gt__(self, other):
- return self.__tagClassId > other
-
- def __ge__(self, other):
- return self.__tagClassId >= other
-
- def __hash__(self):
- return self.__hash
-
- def __getitem__(self, idx):
- if idx == 0:
- return self.__tagClass
- elif idx == 1:
- return self.__tagFormat
- elif idx == 2:
- return self.__tagId
- else:
- raise IndexError()
-
- def __iter__(self):
- yield self.__tagClass
- yield self.__tagFormat
- yield self.__tagId
-
- def __and__(self, otherTag):
- return self.__class__(self.__tagClass & otherTag.tagClass,
- self.__tagFormat & otherTag.tagFormat,
- self.__tagId & otherTag.tagId)
-
- def __or__(self, otherTag):
- return self.__class__(self.__tagClass | otherTag.tagClass,
- self.__tagFormat | otherTag.tagFormat,
- self.__tagId | otherTag.tagId)
-
- @property
- def tagClass(self):
- """ASN.1 tag class
-
- Returns
- -------
- : :py:class:`int`
- Tag class
- """
- return self.__tagClass
-
- @property
- def tagFormat(self):
- """ASN.1 tag format
-
- Returns
- -------
- : :py:class:`int`
- Tag format
- """
- return self.__tagFormat
-
- @property
- def tagId(self):
- """ASN.1 tag ID
-
- Returns
- -------
- : :py:class:`int`
- Tag ID
- """
- return self.__tagId
-
-
- class TagSet(object):
- """Create a collection of ASN.1 tags
-
- Represents a combination of :class:`~pyasn1.type.tag.Tag` objects
- that can be attached to a ASN.1 type to make types distinguishable
- from each other.
-
- *TagSet* objects are immutable and duck-type Python :class:`tuple` objects
- holding arbitrary number of :class:`~pyasn1.type.tag.Tag` objects.
-
- Parameters
- ----------
- baseTag: :class:`~pyasn1.type.tag.Tag`
- Base *Tag* object. This tag survives IMPLICIT tagging.
-
- *superTags: :class:`~pyasn1.type.tag.Tag`
- Additional *Tag* objects taking part in subtyping.
-
- Examples
- --------
- .. code-block:: python
-
- class OrderNumber(NumericString):
- '''
- ASN.1 specification
-
- Order-number ::=
- [APPLICATION 5] IMPLICIT NumericString
- '''
- tagSet = NumericString.tagSet.tagImplicitly(
- Tag(tagClassApplication, tagFormatSimple, 5)
- )
-
- orderNumber = OrderNumber('1234')
- """
- def __init__(self, baseTag=(), *superTags):
- self.__baseTag = baseTag
- self.__superTags = superTags
- self.__superTagsClassId = tuple(
- [(superTag.tagClass, superTag.tagId) for superTag in superTags]
- )
- self.__lenOfSuperTags = len(superTags)
- self.__hash = hash(self.__superTagsClassId)
-
- def __repr__(self):
- representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId)
- for x in self.__superTags])
- if representation:
- representation = 'tags ' + representation
- else:
- representation = 'untagged'
-
- return '<%s object at 0x%x %s>' % (self.__class__.__name__, id(self), representation)
-
- def __add__(self, superTag):
- return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
-
- def __radd__(self, superTag):
- return self.__class__(self.__baseTag, *(superTag,) + self.__superTags)
-
- def __getitem__(self, i):
- if i.__class__ is slice:
- return self.__class__(self.__baseTag, *self.__superTags[i])
- else:
- return self.__superTags[i]
-
- def __eq__(self, other):
- return self.__superTagsClassId == other
-
- def __ne__(self, other):
- return self.__superTagsClassId != other
-
- def __lt__(self, other):
- return self.__superTagsClassId < other
-
- def __le__(self, other):
- return self.__superTagsClassId <= other
-
- def __gt__(self, other):
- return self.__superTagsClassId > other
-
- def __ge__(self, other):
- return self.__superTagsClassId >= other
-
- def __hash__(self):
- return self.__hash
-
- def __len__(self):
- return self.__lenOfSuperTags
-
- @property
- def baseTag(self):
- """Return base ASN.1 tag
-
- Returns
- -------
- : :class:`~pyasn1.type.tag.Tag`
- Base tag of this *TagSet*
- """
- return self.__baseTag
-
- @property
- def superTags(self):
- """Return ASN.1 tags
-
- Returns
- -------
- : :py:class:`tuple`
- Tuple of :class:`~pyasn1.type.tag.Tag` objects that this *TagSet* contains
- """
- return self.__superTags
-
- def tagExplicitly(self, superTag):
- """Return explicitly tagged *TagSet*
-
- Create a new *TagSet* representing callee *TagSet* explicitly tagged
- with passed tag(s). With explicit tagging mode, new tags are appended
- to existing tag(s).
-
- Parameters
- ----------
- superTag: :class:`~pyasn1.type.tag.Tag`
- *Tag* object to tag this *TagSet*
-
- Returns
- -------
- : :class:`~pyasn1.type.tag.TagSet`
- New *TagSet* object
- """
- if superTag.tagClass == tagClassUniversal:
- raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag")
- if superTag.tagFormat != tagFormatConstructed:
- superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId)
- return self + superTag
-
- def tagImplicitly(self, superTag):
- """Return implicitly tagged *TagSet*
-
- Create a new *TagSet* representing callee *TagSet* implicitly tagged
- with passed tag(s). With implicit tagging mode, new tag(s) replace the
- last existing tag.
-
- Parameters
- ----------
- superTag: :class:`~pyasn1.type.tag.Tag`
- *Tag* object to tag this *TagSet*
-
- Returns
- -------
- : :class:`~pyasn1.type.tag.TagSet`
- New *TagSet* object
- """
- if self.__superTags:
- superTag = Tag(superTag.tagClass, self.__superTags[-1].tagFormat, superTag.tagId)
- return self[:-1] + superTag
-
- def isSuperTagSetOf(self, tagSet):
- """Test type relationship against given *TagSet*
-
- The callee is considered to be a supertype of given *TagSet*
- tag-wise if all tags in *TagSet* are present in the callee and
- they are in the same order.
-
- Parameters
- ----------
- tagSet: :class:`~pyasn1.type.tag.TagSet`
- *TagSet* object to evaluate against the callee
-
- Returns
- -------
- : :py:class:`bool`
- `True` if callee is a supertype of *tagSet*
- """
- if len(tagSet) < self.__lenOfSuperTags:
- return False
- return self.__superTags == tagSet[:self.__lenOfSuperTags]
-
- # Backward compatibility
-
- def getBaseTag(self):
- return self.__baseTag
-
- def initTagSet(tag):
- return TagSet(tag, tag)
|