mirror of
https://github.com/thegeeklab/ansible-later.git
synced 2024-07-05 00:20:58 +02:00
334 lines
9.3 KiB
Python
334 lines
9.3 KiB
Python
#
|
|
# This file is part of pyasn1 software.
|
|
#
|
|
# Copyright (c) 2005-2019, 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)
|