Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tag.py 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
  5. # License: http://snmplabs.com/pyasn1/license.html
  6. #
  7. from pyasn1 import error
  8. __all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
  9. 'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
  10. 'tagCategoryImplicit', 'tagCategoryExplicit',
  11. 'tagCategoryUntagged', 'Tag', 'TagSet']
  12. #: Identifier for ASN.1 class UNIVERSAL
  13. tagClassUniversal = 0x00
  14. #: Identifier for ASN.1 class APPLICATION
  15. tagClassApplication = 0x40
  16. #: Identifier for ASN.1 class context-specific
  17. tagClassContext = 0x80
  18. #: Identifier for ASN.1 class private
  19. tagClassPrivate = 0xC0
  20. #: Identifier for "simple" ASN.1 structure (e.g. scalar)
  21. tagFormatSimple = 0x00
  22. #: Identifier for "constructed" ASN.1 structure (e.g. may have inner components)
  23. tagFormatConstructed = 0x20
  24. tagCategoryImplicit = 0x01
  25. tagCategoryExplicit = 0x02
  26. tagCategoryUntagged = 0x04
  27. class Tag(object):
  28. """Create ASN.1 tag
  29. Represents ASN.1 tag that can be attached to a ASN.1 type to make
  30. types distinguishable from each other.
  31. *Tag* objects are immutable and duck-type Python :class:`tuple` objects
  32. holding three integer components of a tag.
  33. Parameters
  34. ----------
  35. tagClass: :py:class:`int`
  36. Tag *class* value
  37. tagFormat: :py:class:`int`
  38. Tag *format* value
  39. tagId: :py:class:`int`
  40. Tag ID value
  41. """
  42. def __init__(self, tagClass, tagFormat, tagId):
  43. if tagId < 0:
  44. raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId)
  45. self.__tagClass = tagClass
  46. self.__tagFormat = tagFormat
  47. self.__tagId = tagId
  48. self.__tagClassId = tagClass, tagId
  49. self.__hash = hash(self.__tagClassId)
  50. def __repr__(self):
  51. representation = '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
  52. return '<%s object at 0x%x tag %s>' % (self.__class__.__name__, id(self), representation)
  53. def __eq__(self, other):
  54. return self.__tagClassId == other
  55. def __ne__(self, other):
  56. return self.__tagClassId != other
  57. def __lt__(self, other):
  58. return self.__tagClassId < other
  59. def __le__(self, other):
  60. return self.__tagClassId <= other
  61. def __gt__(self, other):
  62. return self.__tagClassId > other
  63. def __ge__(self, other):
  64. return self.__tagClassId >= other
  65. def __hash__(self):
  66. return self.__hash
  67. def __getitem__(self, idx):
  68. if idx == 0:
  69. return self.__tagClass
  70. elif idx == 1:
  71. return self.__tagFormat
  72. elif idx == 2:
  73. return self.__tagId
  74. else:
  75. raise IndexError()
  76. def __iter__(self):
  77. yield self.__tagClass
  78. yield self.__tagFormat
  79. yield self.__tagId
  80. def __and__(self, otherTag):
  81. return self.__class__(self.__tagClass & otherTag.tagClass,
  82. self.__tagFormat & otherTag.tagFormat,
  83. self.__tagId & otherTag.tagId)
  84. def __or__(self, otherTag):
  85. return self.__class__(self.__tagClass | otherTag.tagClass,
  86. self.__tagFormat | otherTag.tagFormat,
  87. self.__tagId | otherTag.tagId)
  88. @property
  89. def tagClass(self):
  90. """ASN.1 tag class
  91. Returns
  92. -------
  93. : :py:class:`int`
  94. Tag class
  95. """
  96. return self.__tagClass
  97. @property
  98. def tagFormat(self):
  99. """ASN.1 tag format
  100. Returns
  101. -------
  102. : :py:class:`int`
  103. Tag format
  104. """
  105. return self.__tagFormat
  106. @property
  107. def tagId(self):
  108. """ASN.1 tag ID
  109. Returns
  110. -------
  111. : :py:class:`int`
  112. Tag ID
  113. """
  114. return self.__tagId
  115. class TagSet(object):
  116. """Create a collection of ASN.1 tags
  117. Represents a combination of :class:`~pyasn1.type.tag.Tag` objects
  118. that can be attached to a ASN.1 type to make types distinguishable
  119. from each other.
  120. *TagSet* objects are immutable and duck-type Python :class:`tuple` objects
  121. holding arbitrary number of :class:`~pyasn1.type.tag.Tag` objects.
  122. Parameters
  123. ----------
  124. baseTag: :class:`~pyasn1.type.tag.Tag`
  125. Base *Tag* object. This tag survives IMPLICIT tagging.
  126. *superTags: :class:`~pyasn1.type.tag.Tag`
  127. Additional *Tag* objects taking part in subtyping.
  128. Examples
  129. --------
  130. .. code-block:: python
  131. class OrderNumber(NumericString):
  132. '''
  133. ASN.1 specification
  134. Order-number ::=
  135. [APPLICATION 5] IMPLICIT NumericString
  136. '''
  137. tagSet = NumericString.tagSet.tagImplicitly(
  138. Tag(tagClassApplication, tagFormatSimple, 5)
  139. )
  140. orderNumber = OrderNumber('1234')
  141. """
  142. def __init__(self, baseTag=(), *superTags):
  143. self.__baseTag = baseTag
  144. self.__superTags = superTags
  145. self.__superTagsClassId = tuple(
  146. [(superTag.tagClass, superTag.tagId) for superTag in superTags]
  147. )
  148. self.__lenOfSuperTags = len(superTags)
  149. self.__hash = hash(self.__superTagsClassId)
  150. def __repr__(self):
  151. representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId)
  152. for x in self.__superTags])
  153. if representation:
  154. representation = 'tags ' + representation
  155. else:
  156. representation = 'untagged'
  157. return '<%s object at 0x%x %s>' % (self.__class__.__name__, id(self), representation)
  158. def __add__(self, superTag):
  159. return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
  160. def __radd__(self, superTag):
  161. return self.__class__(self.__baseTag, *(superTag,) + self.__superTags)
  162. def __getitem__(self, i):
  163. if i.__class__ is slice:
  164. return self.__class__(self.__baseTag, *self.__superTags[i])
  165. else:
  166. return self.__superTags[i]
  167. def __eq__(self, other):
  168. return self.__superTagsClassId == other
  169. def __ne__(self, other):
  170. return self.__superTagsClassId != other
  171. def __lt__(self, other):
  172. return self.__superTagsClassId < other
  173. def __le__(self, other):
  174. return self.__superTagsClassId <= other
  175. def __gt__(self, other):
  176. return self.__superTagsClassId > other
  177. def __ge__(self, other):
  178. return self.__superTagsClassId >= other
  179. def __hash__(self):
  180. return self.__hash
  181. def __len__(self):
  182. return self.__lenOfSuperTags
  183. @property
  184. def baseTag(self):
  185. """Return base ASN.1 tag
  186. Returns
  187. -------
  188. : :class:`~pyasn1.type.tag.Tag`
  189. Base tag of this *TagSet*
  190. """
  191. return self.__baseTag
  192. @property
  193. def superTags(self):
  194. """Return ASN.1 tags
  195. Returns
  196. -------
  197. : :py:class:`tuple`
  198. Tuple of :class:`~pyasn1.type.tag.Tag` objects that this *TagSet* contains
  199. """
  200. return self.__superTags
  201. def tagExplicitly(self, superTag):
  202. """Return explicitly tagged *TagSet*
  203. Create a new *TagSet* representing callee *TagSet* explicitly tagged
  204. with passed tag(s). With explicit tagging mode, new tags are appended
  205. to existing tag(s).
  206. Parameters
  207. ----------
  208. superTag: :class:`~pyasn1.type.tag.Tag`
  209. *Tag* object to tag this *TagSet*
  210. Returns
  211. -------
  212. : :class:`~pyasn1.type.tag.TagSet`
  213. New *TagSet* object
  214. """
  215. if superTag.tagClass == tagClassUniversal:
  216. raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag")
  217. if superTag.tagFormat != tagFormatConstructed:
  218. superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId)
  219. return self + superTag
  220. def tagImplicitly(self, superTag):
  221. """Return implicitly tagged *TagSet*
  222. Create a new *TagSet* representing callee *TagSet* implicitly tagged
  223. with passed tag(s). With implicit tagging mode, new tag(s) replace the
  224. last existing tag.
  225. Parameters
  226. ----------
  227. superTag: :class:`~pyasn1.type.tag.Tag`
  228. *Tag* object to tag this *TagSet*
  229. Returns
  230. -------
  231. : :class:`~pyasn1.type.tag.TagSet`
  232. New *TagSet* object
  233. """
  234. if self.__superTags:
  235. superTag = Tag(superTag.tagClass, self.__superTags[-1].tagFormat, superTag.tagId)
  236. return self[:-1] + superTag
  237. def isSuperTagSetOf(self, tagSet):
  238. """Test type relationship against given *TagSet*
  239. The callee is considered to be a supertype of given *TagSet*
  240. tag-wise if all tags in *TagSet* are present in the callee and
  241. they are in the same order.
  242. Parameters
  243. ----------
  244. tagSet: :class:`~pyasn1.type.tag.TagSet`
  245. *TagSet* object to evaluate against the callee
  246. Returns
  247. -------
  248. : :py:class:`bool`
  249. `True` if callee is a supertype of *tagSet*
  250. """
  251. if len(tagSet) < self.__lenOfSuperTags:
  252. return False
  253. return self.__superTags == tagSet[:self.__lenOfSuperTags]
  254. # Backward compatibility
  255. def getBaseTag(self):
  256. return self.__baseTag
  257. def initTagSet(tag):
  258. return TagSet(tag, tag)