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.

encoder.py 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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 debug
  8. from pyasn1 import error
  9. from pyasn1.codec.ber import eoo
  10. from pyasn1.compat.integer import to_bytes
  11. from pyasn1.compat.octets import (int2oct, oct2int, ints2octs, null,
  12. str2octs, isOctetsType)
  13. from pyasn1.type import char
  14. from pyasn1.type import tag
  15. from pyasn1.type import univ
  16. from pyasn1.type import useful
  17. __all__ = ['encode']
  18. class AbstractItemEncoder(object):
  19. supportIndefLenMode = True
  20. # An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
  21. eooIntegerSubstrate = (0, 0)
  22. eooOctetsSubstrate = ints2octs(eooIntegerSubstrate)
  23. # noinspection PyMethodMayBeStatic
  24. def encodeTag(self, singleTag, isConstructed):
  25. tagClass, tagFormat, tagId = singleTag
  26. encodedTag = tagClass | tagFormat
  27. if isConstructed:
  28. encodedTag |= tag.tagFormatConstructed
  29. if tagId < 31:
  30. return encodedTag | tagId,
  31. else:
  32. substrate = tagId & 0x7f,
  33. tagId >>= 7
  34. while tagId:
  35. substrate = (0x80 | (tagId & 0x7f),) + substrate
  36. tagId >>= 7
  37. return (encodedTag | 0x1F,) + substrate
  38. def encodeLength(self, length, defMode):
  39. if not defMode and self.supportIndefLenMode:
  40. return (0x80,)
  41. if length < 0x80:
  42. return length,
  43. else:
  44. substrate = ()
  45. while length:
  46. substrate = (length & 0xff,) + substrate
  47. length >>= 8
  48. substrateLen = len(substrate)
  49. if substrateLen > 126:
  50. raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
  51. return (0x80 | substrateLen,) + substrate
  52. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  53. raise error.PyAsn1Error('Not implemented')
  54. def encode(self, value, asn1Spec=None, encodeFun=None, **options):
  55. if asn1Spec is None:
  56. tagSet = value.tagSet
  57. else:
  58. tagSet = asn1Spec.tagSet
  59. # untagged item?
  60. if not tagSet:
  61. substrate, isConstructed, isOctets = self.encodeValue(
  62. value, asn1Spec, encodeFun, **options
  63. )
  64. return substrate
  65. defMode = options.get('defMode', True)
  66. for idx, singleTag in enumerate(tagSet.superTags):
  67. defModeOverride = defMode
  68. # base tag?
  69. if not idx:
  70. substrate, isConstructed, isOctets = self.encodeValue(
  71. value, asn1Spec, encodeFun, **options
  72. )
  73. if not substrate and isConstructed and options.get('ifNotEmpty', False):
  74. return substrate
  75. # primitive form implies definite mode
  76. if not isConstructed:
  77. defModeOverride = True
  78. header = self.encodeTag(singleTag, isConstructed)
  79. header += self.encodeLength(len(substrate), defModeOverride)
  80. if isOctets:
  81. substrate = ints2octs(header) + substrate
  82. if not defModeOverride:
  83. substrate += self.eooOctetsSubstrate
  84. else:
  85. substrate = header + substrate
  86. if not defModeOverride:
  87. substrate += self.eooIntegerSubstrate
  88. if not isOctets:
  89. substrate = ints2octs(substrate)
  90. return substrate
  91. class EndOfOctetsEncoder(AbstractItemEncoder):
  92. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  93. return null, False, True
  94. class BooleanEncoder(AbstractItemEncoder):
  95. supportIndefLenMode = False
  96. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  97. return value and (1,) or (0,), False, False
  98. class IntegerEncoder(AbstractItemEncoder):
  99. supportIndefLenMode = False
  100. supportCompactZero = False
  101. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  102. if value == 0:
  103. # de-facto way to encode zero
  104. if self.supportCompactZero:
  105. return (), False, False
  106. else:
  107. return (0,), False, False
  108. return to_bytes(int(value), signed=True), False, True
  109. class BitStringEncoder(AbstractItemEncoder):
  110. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  111. if asn1Spec is not None:
  112. # TODO: try to avoid ASN.1 schema instantiation
  113. value = asn1Spec.clone(value)
  114. valueLength = len(value)
  115. if valueLength % 8:
  116. alignedValue = value << (8 - valueLength % 8)
  117. else:
  118. alignedValue = value
  119. maxChunkSize = options.get('maxChunkSize', 0)
  120. if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8:
  121. substrate = alignedValue.asOctets()
  122. return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
  123. baseTag = value.tagSet.baseTag
  124. # strip off explicit tags
  125. if baseTag:
  126. tagSet = tag.TagSet(baseTag, baseTag)
  127. else:
  128. tagSet = tag.TagSet()
  129. alignedValue = alignedValue.clone(tagSet=tagSet)
  130. stop = 0
  131. substrate = null
  132. while stop < valueLength:
  133. start = stop
  134. stop = min(start + maxChunkSize * 8, valueLength)
  135. substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options)
  136. return substrate, True, True
  137. class OctetStringEncoder(AbstractItemEncoder):
  138. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  139. if asn1Spec is None:
  140. substrate = value.asOctets()
  141. elif not isOctetsType(value):
  142. substrate = asn1Spec.clone(value).asOctets()
  143. else:
  144. substrate = value
  145. maxChunkSize = options.get('maxChunkSize', 0)
  146. if not maxChunkSize or len(substrate) <= maxChunkSize:
  147. return substrate, False, True
  148. else:
  149. # strip off explicit tags for inner chunks
  150. if asn1Spec is None:
  151. baseTag = value.tagSet.baseTag
  152. # strip off explicit tags
  153. if baseTag:
  154. tagSet = tag.TagSet(baseTag, baseTag)
  155. else:
  156. tagSet = tag.TagSet()
  157. asn1Spec = value.clone(tagSet=tagSet)
  158. elif not isOctetsType(value):
  159. baseTag = asn1Spec.tagSet.baseTag
  160. # strip off explicit tags
  161. if baseTag:
  162. tagSet = tag.TagSet(baseTag, baseTag)
  163. else:
  164. tagSet = tag.TagSet()
  165. asn1Spec = asn1Spec.clone(tagSet=tagSet)
  166. pos = 0
  167. substrate = null
  168. while True:
  169. chunk = value[pos:pos + maxChunkSize]
  170. if not chunk:
  171. break
  172. substrate += encodeFun(chunk, asn1Spec, **options)
  173. pos += maxChunkSize
  174. return substrate, True, True
  175. class NullEncoder(AbstractItemEncoder):
  176. supportIndefLenMode = False
  177. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  178. return null, False, True
  179. class ObjectIdentifierEncoder(AbstractItemEncoder):
  180. supportIndefLenMode = False
  181. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  182. if asn1Spec is not None:
  183. value = asn1Spec.clone(value)
  184. oid = value.asTuple()
  185. # Build the first pair
  186. try:
  187. first = oid[0]
  188. second = oid[1]
  189. except IndexError:
  190. raise error.PyAsn1Error('Short OID %s' % (value,))
  191. if 0 <= second <= 39:
  192. if first == 1:
  193. oid = (second + 40,) + oid[2:]
  194. elif first == 0:
  195. oid = (second,) + oid[2:]
  196. elif first == 2:
  197. oid = (second + 80,) + oid[2:]
  198. else:
  199. raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
  200. elif first == 2:
  201. oid = (second + 80,) + oid[2:]
  202. else:
  203. raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
  204. octets = ()
  205. # Cycle through subIds
  206. for subOid in oid:
  207. if 0 <= subOid <= 127:
  208. # Optimize for the common case
  209. octets += (subOid,)
  210. elif subOid > 127:
  211. # Pack large Sub-Object IDs
  212. res = (subOid & 0x7f,)
  213. subOid >>= 7
  214. while subOid:
  215. res = (0x80 | (subOid & 0x7f),) + res
  216. subOid >>= 7
  217. # Add packed Sub-Object ID to resulted Object ID
  218. octets += res
  219. else:
  220. raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value))
  221. return octets, False, False
  222. class RealEncoder(AbstractItemEncoder):
  223. supportIndefLenMode = 0
  224. binEncBase = 2 # set to None to choose encoding base automatically
  225. @staticmethod
  226. def _dropFloatingPoint(m, encbase, e):
  227. ms, es = 1, 1
  228. if m < 0:
  229. ms = -1 # mantissa sign
  230. if e < 0:
  231. es = -1 # exponenta sign
  232. m *= ms
  233. if encbase == 8:
  234. m *= 2 ** (abs(e) % 3 * es)
  235. e = abs(e) // 3 * es
  236. elif encbase == 16:
  237. m *= 2 ** (abs(e) % 4 * es)
  238. e = abs(e) // 4 * es
  239. while True:
  240. if int(m) != m:
  241. m *= encbase
  242. e -= 1
  243. continue
  244. break
  245. return ms, int(m), encbase, e
  246. def _chooseEncBase(self, value):
  247. m, b, e = value
  248. encBase = [2, 8, 16]
  249. if value.binEncBase in encBase:
  250. return self._dropFloatingPoint(m, value.binEncBase, e)
  251. elif self.binEncBase in encBase:
  252. return self._dropFloatingPoint(m, self.binEncBase, e)
  253. # auto choosing base 2/8/16
  254. mantissa = [m, m, m]
  255. exponenta = [e, e, e]
  256. sign = 1
  257. encbase = 2
  258. e = float('inf')
  259. for i in range(3):
  260. (sign,
  261. mantissa[i],
  262. encBase[i],
  263. exponenta[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponenta[i])
  264. if abs(exponenta[i]) < abs(e) or (abs(exponenta[i]) == abs(e) and mantissa[i] < m):
  265. e = exponenta[i]
  266. m = int(mantissa[i])
  267. encbase = encBase[i]
  268. return sign, m, encbase, e
  269. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  270. if asn1Spec is not None:
  271. value = asn1Spec.clone(value)
  272. if value.isPlusInf:
  273. return (0x40,), False, False
  274. if value.isMinusInf:
  275. return (0x41,), False, False
  276. m, b, e = value
  277. if not m:
  278. return null, False, True
  279. if b == 10:
  280. return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True
  281. elif b == 2:
  282. fo = 0x80 # binary encoding
  283. ms, m, encbase, e = self._chooseEncBase(value)
  284. if ms < 0: # mantissa sign
  285. fo |= 0x40 # sign bit
  286. # exponenta & mantissa normalization
  287. if encbase == 2:
  288. while m & 0x1 == 0:
  289. m >>= 1
  290. e += 1
  291. elif encbase == 8:
  292. while m & 0x7 == 0:
  293. m >>= 3
  294. e += 1
  295. fo |= 0x10
  296. else: # encbase = 16
  297. while m & 0xf == 0:
  298. m >>= 4
  299. e += 1
  300. fo |= 0x20
  301. sf = 0 # scale factor
  302. while m & 0x1 == 0:
  303. m >>= 1
  304. sf += 1
  305. if sf > 3:
  306. raise error.PyAsn1Error('Scale factor overflow') # bug if raised
  307. fo |= sf << 2
  308. eo = null
  309. if e == 0 or e == -1:
  310. eo = int2oct(e & 0xff)
  311. else:
  312. while e not in (0, -1):
  313. eo = int2oct(e & 0xff) + eo
  314. e >>= 8
  315. if e == 0 and eo and oct2int(eo[0]) & 0x80:
  316. eo = int2oct(0) + eo
  317. if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
  318. eo = int2oct(0xff) + eo
  319. n = len(eo)
  320. if n > 0xff:
  321. raise error.PyAsn1Error('Real exponent overflow')
  322. if n == 1:
  323. pass
  324. elif n == 2:
  325. fo |= 1
  326. elif n == 3:
  327. fo |= 2
  328. else:
  329. fo |= 3
  330. eo = int2oct(n & 0xff) + eo
  331. po = null
  332. while m:
  333. po = int2oct(m & 0xff) + po
  334. m >>= 8
  335. substrate = int2oct(fo) + eo + po
  336. return substrate, False, True
  337. else:
  338. raise error.PyAsn1Error('Prohibited Real base %s' % b)
  339. class SequenceEncoder(AbstractItemEncoder):
  340. omitEmptyOptionals = False
  341. # TODO: handling three flavors of input is too much -- split over codecs
  342. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  343. substrate = null
  344. if asn1Spec is None:
  345. # instance of ASN.1 schema
  346. value.verifySizeSpec()
  347. namedTypes = value.componentType
  348. for idx, component in enumerate(value.values()):
  349. if namedTypes:
  350. namedType = namedTypes[idx]
  351. if namedType.isOptional and not component.isValue:
  352. continue
  353. if namedType.isDefaulted and component == namedType.asn1Object:
  354. continue
  355. if self.omitEmptyOptionals:
  356. options.update(ifNotEmpty=namedType.isOptional)
  357. chunk = encodeFun(component, asn1Spec, **options)
  358. # wrap open type blob if needed
  359. if namedTypes and namedType.openType:
  360. wrapType = namedType.asn1Object
  361. if wrapType.tagSet and not wrapType.isSameTypeWith(component):
  362. chunk = encodeFun(chunk, wrapType, **options)
  363. substrate += chunk
  364. else:
  365. # bare Python value + ASN.1 schema
  366. for idx, namedType in enumerate(asn1Spec.componentType.namedTypes):
  367. try:
  368. component = value[namedType.name]
  369. except KeyError:
  370. raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value))
  371. if namedType.isOptional and namedType.name not in value:
  372. continue
  373. if namedType.isDefaulted and component == namedType.asn1Object:
  374. continue
  375. if self.omitEmptyOptionals:
  376. options.update(ifNotEmpty=namedType.isOptional)
  377. chunk = encodeFun(component, asn1Spec[idx], **options)
  378. # wrap open type blob if needed
  379. if namedType.openType:
  380. wrapType = namedType.asn1Object
  381. if wrapType.tagSet and not wrapType.isSameTypeWith(component):
  382. chunk = encodeFun(chunk, wrapType, **options)
  383. substrate += chunk
  384. return substrate, True, True
  385. class SequenceOfEncoder(AbstractItemEncoder):
  386. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  387. if asn1Spec is None:
  388. value.verifySizeSpec()
  389. else:
  390. asn1Spec = asn1Spec.componentType
  391. substrate = null
  392. for idx, component in enumerate(value):
  393. substrate += encodeFun(value[idx], asn1Spec, **options)
  394. return substrate, True, True
  395. class ChoiceEncoder(AbstractItemEncoder):
  396. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  397. if asn1Spec is None:
  398. component = value.getComponent()
  399. else:
  400. names = [namedType.name for namedType in asn1Spec.componentType.namedTypes
  401. if namedType.name in value]
  402. if len(names) != 1:
  403. raise error.PyAsn1Error('%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value))
  404. name = names[0]
  405. component = value[name]
  406. asn1Spec = asn1Spec[name]
  407. return encodeFun(component, asn1Spec, **options), True, True
  408. class AnyEncoder(OctetStringEncoder):
  409. def encodeValue(self, value, asn1Spec, encodeFun, **options):
  410. if asn1Spec is None:
  411. value = value.asOctets()
  412. elif not isOctetsType(value):
  413. value = asn1Spec.clone(value).asOctets()
  414. return value, not options.get('defMode', True), True
  415. tagMap = {
  416. eoo.endOfOctets.tagSet: EndOfOctetsEncoder(),
  417. univ.Boolean.tagSet: BooleanEncoder(),
  418. univ.Integer.tagSet: IntegerEncoder(),
  419. univ.BitString.tagSet: BitStringEncoder(),
  420. univ.OctetString.tagSet: OctetStringEncoder(),
  421. univ.Null.tagSet: NullEncoder(),
  422. univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),
  423. univ.Enumerated.tagSet: IntegerEncoder(),
  424. univ.Real.tagSet: RealEncoder(),
  425. # Sequence & Set have same tags as SequenceOf & SetOf
  426. univ.SequenceOf.tagSet: SequenceOfEncoder(),
  427. univ.SetOf.tagSet: SequenceOfEncoder(),
  428. univ.Choice.tagSet: ChoiceEncoder(),
  429. # character string types
  430. char.UTF8String.tagSet: OctetStringEncoder(),
  431. char.NumericString.tagSet: OctetStringEncoder(),
  432. char.PrintableString.tagSet: OctetStringEncoder(),
  433. char.TeletexString.tagSet: OctetStringEncoder(),
  434. char.VideotexString.tagSet: OctetStringEncoder(),
  435. char.IA5String.tagSet: OctetStringEncoder(),
  436. char.GraphicString.tagSet: OctetStringEncoder(),
  437. char.VisibleString.tagSet: OctetStringEncoder(),
  438. char.GeneralString.tagSet: OctetStringEncoder(),
  439. char.UniversalString.tagSet: OctetStringEncoder(),
  440. char.BMPString.tagSet: OctetStringEncoder(),
  441. # useful types
  442. useful.ObjectDescriptor.tagSet: OctetStringEncoder(),
  443. useful.GeneralizedTime.tagSet: OctetStringEncoder(),
  444. useful.UTCTime.tagSet: OctetStringEncoder()
  445. }
  446. # Put in ambiguous & non-ambiguous types for faster codec lookup
  447. typeMap = {
  448. univ.Boolean.typeId: BooleanEncoder(),
  449. univ.Integer.typeId: IntegerEncoder(),
  450. univ.BitString.typeId: BitStringEncoder(),
  451. univ.OctetString.typeId: OctetStringEncoder(),
  452. univ.Null.typeId: NullEncoder(),
  453. univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),
  454. univ.Enumerated.typeId: IntegerEncoder(),
  455. univ.Real.typeId: RealEncoder(),
  456. # Sequence & Set have same tags as SequenceOf & SetOf
  457. univ.Set.typeId: SequenceEncoder(),
  458. univ.SetOf.typeId: SequenceOfEncoder(),
  459. univ.Sequence.typeId: SequenceEncoder(),
  460. univ.SequenceOf.typeId: SequenceOfEncoder(),
  461. univ.Choice.typeId: ChoiceEncoder(),
  462. univ.Any.typeId: AnyEncoder(),
  463. # character string types
  464. char.UTF8String.typeId: OctetStringEncoder(),
  465. char.NumericString.typeId: OctetStringEncoder(),
  466. char.PrintableString.typeId: OctetStringEncoder(),
  467. char.TeletexString.typeId: OctetStringEncoder(),
  468. char.VideotexString.typeId: OctetStringEncoder(),
  469. char.IA5String.typeId: OctetStringEncoder(),
  470. char.GraphicString.typeId: OctetStringEncoder(),
  471. char.VisibleString.typeId: OctetStringEncoder(),
  472. char.GeneralString.typeId: OctetStringEncoder(),
  473. char.UniversalString.typeId: OctetStringEncoder(),
  474. char.BMPString.typeId: OctetStringEncoder(),
  475. # useful types
  476. useful.ObjectDescriptor.typeId: OctetStringEncoder(),
  477. useful.GeneralizedTime.typeId: OctetStringEncoder(),
  478. useful.UTCTime.typeId: OctetStringEncoder()
  479. }
  480. class Encoder(object):
  481. fixedDefLengthMode = None
  482. fixedChunkSize = None
  483. # noinspection PyDefaultArgument
  484. def __init__(self, tagMap, typeMap={}):
  485. self.__tagMap = tagMap
  486. self.__typeMap = typeMap
  487. def __call__(self, value, asn1Spec=None, **options):
  488. try:
  489. if asn1Spec is None:
  490. typeId = value.typeId
  491. else:
  492. typeId = asn1Spec.typeId
  493. except AttributeError:
  494. raise error.PyAsn1Error('Value %r is not ASN.1 type instance '
  495. 'and "asn1Spec" not given' % (value,))
  496. if debug.logger & debug.flagEncoder:
  497. logger = debug.logger
  498. else:
  499. logger = None
  500. if logger:
  501. logger('encoder called in %sdef mode, chunk size %s for '
  502. 'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value))
  503. if self.fixedDefLengthMode is not None:
  504. options.update(defMode=self.fixedDefLengthMode)
  505. if self.fixedChunkSize is not None:
  506. options.update(maxChunkSize=self.fixedChunkSize)
  507. try:
  508. concreteEncoder = self.__typeMap[typeId]
  509. if logger:
  510. logger('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId))
  511. except KeyError:
  512. if asn1Spec is None:
  513. tagSet = value.tagSet
  514. else:
  515. tagSet = asn1Spec.tagSet
  516. # use base type for codec lookup to recover untagged types
  517. baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)
  518. try:
  519. concreteEncoder = self.__tagMap[baseTagSet]
  520. except KeyError:
  521. raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))
  522. if logger:
  523. logger('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet))
  524. substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
  525. if logger:
  526. logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))
  527. return substrate
  528. #: Turns ASN.1 object into BER octet stream.
  529. #:
  530. #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
  531. #: walks all its components recursively and produces a BER octet stream.
  532. #:
  533. #: Parameters
  534. #: ----------
  535. #: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
  536. #: A Python or pyasn1 object to encode. If Python object is given, `asnSpec`
  537. #: parameter is required to guide the encoding process.
  538. #:
  539. #: Keyword Args
  540. #: ------------
  541. #: asn1Spec:
  542. #: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
  543. #:
  544. #: defMode: :py:class:`bool`
  545. #: If `False`, produces indefinite length encoding
  546. #:
  547. #: maxChunkSize: :py:class:`int`
  548. #: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
  549. #:
  550. #: Returns
  551. #: -------
  552. #: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
  553. #: Given ASN.1 object encoded into BER octetstream
  554. #:
  555. #: Raises
  556. #: ------
  557. #: :py:class:`~pyasn1.error.PyAsn1Error`
  558. #: On encoding errors
  559. #:
  560. #: Examples
  561. #: --------
  562. #: Encode Python value into BER with ASN.1 schema
  563. #:
  564. #: .. code-block:: pycon
  565. #:
  566. #: >>> seq = SequenceOf(componentType=Integer())
  567. #: >>> encode([1, 2, 3], asn1Spec=seq)
  568. #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
  569. #:
  570. #: Encode ASN.1 value object into BER
  571. #:
  572. #: .. code-block:: pycon
  573. #:
  574. #: >>> seq = SequenceOf(componentType=Integer())
  575. #: >>> seq.extend([1, 2, 3])
  576. #: >>> encode(seq)
  577. #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
  578. #:
  579. encode = Encoder(tagMap, typeMap)