Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
encoder.py955 linesDownload Raw Back to ber
1#2# This file is part of pyasn1 software.3#4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>5# License: https://pyasn1.readthedocs.io/en/latest/license.html6#7import sys8import warnings9 10from pyasn1 import debug11from pyasn1 import error12from pyasn1.codec.ber import eoo13from pyasn1.compat import _MISSING14from pyasn1.compat.integer import to_bytes15from pyasn1.type import char16from pyasn1.type import tag17from pyasn1.type import univ18from pyasn1.type import useful19 20__all__ = ['Encoder', 'encode']21 22LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER)23 24 25class AbstractItemEncoder(object):26    supportIndefLenMode = True27 28    # An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`29    eooIntegerSubstrate = (0, 0)30    eooOctetsSubstrate = bytes(eooIntegerSubstrate)31 32    # noinspection PyMethodMayBeStatic33    def encodeTag(self, singleTag, isConstructed):34        tagClass, tagFormat, tagId = singleTag35        encodedTag = tagClass | tagFormat36        if isConstructed:37            encodedTag |= tag.tagFormatConstructed38 39        if tagId < 31:40            return encodedTag | tagId,41 42        else:43            substrate = tagId & 0x7f,44 45            tagId >>= 746 47            while tagId:48                substrate = (0x80 | (tagId & 0x7f),) + substrate49                tagId >>= 750 51            return (encodedTag | 0x1F,) + substrate52 53    def encodeLength(self, length, defMode):54        if not defMode and self.supportIndefLenMode:55            return (0x80,)56 57        if length < 0x80:58            return length,59 60        else:61            substrate = ()62            while length:63                substrate = (length & 0xff,) + substrate64                length >>= 865 66            substrateLen = len(substrate)67 68            if substrateLen > 126:69                raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)70 71            return (0x80 | substrateLen,) + substrate72 73    def encodeValue(self, value, asn1Spec, encodeFun, **options):74        raise error.PyAsn1Error('Not implemented')75 76    def encode(self, value, asn1Spec=None, encodeFun=None, **options):77 78        if asn1Spec is None:79            tagSet = value.tagSet80        else:81            tagSet = asn1Spec.tagSet82 83        # untagged item?84        if not tagSet:85            substrate, isConstructed, isOctets = self.encodeValue(86                value, asn1Spec, encodeFun, **options87            )88            return substrate89 90        defMode = options.get('defMode', True)91 92        substrate = b''93 94        for idx, singleTag in enumerate(tagSet.superTags):95 96            defModeOverride = defMode97 98            # base tag?99            if not idx:100                try:101                    substrate, isConstructed, isOctets = self.encodeValue(102                        value, asn1Spec, encodeFun, **options103                    )104 105                except error.PyAsn1Error as exc:106                    raise error.PyAsn1Error(107                        'Error encoding %r: %s' % (value, exc))108 109                if LOG:110                    LOG('encoded %svalue %s into %s' % (111                        isConstructed and 'constructed ' or '', value, substrate112                    ))113 114                if not substrate and isConstructed and options.get('ifNotEmpty', False):115                    return substrate116 117                if not isConstructed:118                    defModeOverride = True119 120                    if LOG:121                        LOG('overridden encoding mode into definitive for primitive type')122 123            header = self.encodeTag(singleTag, isConstructed)124 125            if LOG:126                LOG('encoded %stag %s into %s' % (127                    isConstructed and 'constructed ' or '',128                    singleTag, debug.hexdump(bytes(header))))129 130            header += self.encodeLength(len(substrate), defModeOverride)131 132            if LOG:133                LOG('encoded %s octets (tag + payload) into %s' % (134                    len(substrate), debug.hexdump(bytes(header))))135 136            if isOctets:137                substrate = bytes(header) + substrate138 139                if not defModeOverride:140                    substrate += self.eooOctetsSubstrate141 142            else:143                substrate = header + substrate144 145                if not defModeOverride:146                    substrate += self.eooIntegerSubstrate147 148        if not isOctets:149            substrate = bytes(substrate)150 151        return substrate152 153 154class EndOfOctetsEncoder(AbstractItemEncoder):155    def encodeValue(self, value, asn1Spec, encodeFun, **options):156        return b'', False, True157 158 159class BooleanEncoder(AbstractItemEncoder):160    supportIndefLenMode = False161 162    def encodeValue(self, value, asn1Spec, encodeFun, **options):163        return value and (1,) or (0,), False, False164 165 166class IntegerEncoder(AbstractItemEncoder):167    supportIndefLenMode = False168    supportCompactZero = False169 170    def encodeValue(self, value, asn1Spec, encodeFun, **options):171        if value == 0:172            if LOG:173                LOG('encoding %spayload for zero INTEGER' % (174                    self.supportCompactZero and 'no ' or ''175                ))176 177            # de-facto way to encode zero178            if self.supportCompactZero:179                return (), False, False180            else:181                return (0,), False, False182 183        return to_bytes(int(value), signed=True), False, True184 185 186class BitStringEncoder(AbstractItemEncoder):187    def encodeValue(self, value, asn1Spec, encodeFun, **options):188        if asn1Spec is not None:189            # TODO: try to avoid ASN.1 schema instantiation190            value = asn1Spec.clone(value)191 192        valueLength = len(value)193        if valueLength % 8:194            alignedValue = value << (8 - valueLength % 8)195        else:196            alignedValue = value197 198        maxChunkSize = options.get('maxChunkSize', 0)199        if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8:200            substrate = alignedValue.asOctets()201            return bytes((len(substrate) * 8 - valueLength,)) + substrate, False, True202 203        if LOG:204            LOG('encoding into up to %s-octet chunks' % maxChunkSize)205 206        baseTag = value.tagSet.baseTag207 208        # strip off explicit tags209        if baseTag:210            tagSet = tag.TagSet(baseTag, baseTag)211 212        else:213            tagSet = tag.TagSet()214 215        alignedValue = alignedValue.clone(tagSet=tagSet)216 217        stop = 0218        substrate = b''219        while stop < valueLength:220            start = stop221            stop = min(start + maxChunkSize * 8, valueLength)222            substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options)223 224        return substrate, True, True225 226 227class OctetStringEncoder(AbstractItemEncoder):228 229    def encodeValue(self, value, asn1Spec, encodeFun, **options):230 231        if asn1Spec is None:232            substrate = value.asOctets()233 234        elif not isinstance(value, bytes):235            substrate = asn1Spec.clone(value).asOctets()236 237        else:238            substrate = value239 240        maxChunkSize = options.get('maxChunkSize', 0)241 242        if not maxChunkSize or len(substrate) <= maxChunkSize:243            return substrate, False, True244 245        if LOG:246            LOG('encoding into up to %s-octet chunks' % maxChunkSize)247 248        # strip off explicit tags for inner chunks249 250        if asn1Spec is None:251            baseTag = value.tagSet.baseTag252 253            # strip off explicit tags254            if baseTag:255                tagSet = tag.TagSet(baseTag, baseTag)256 257            else:258                tagSet = tag.TagSet()259 260            asn1Spec = value.clone(tagSet=tagSet)261 262        elif not isinstance(value, bytes):263            baseTag = asn1Spec.tagSet.baseTag264 265            # strip off explicit tags266            if baseTag:267                tagSet = tag.TagSet(baseTag, baseTag)268 269            else:270                tagSet = tag.TagSet()271 272            asn1Spec = asn1Spec.clone(tagSet=tagSet)273 274        pos = 0275        substrate = b''276 277        while True:278            chunk = value[pos:pos + maxChunkSize]279            if not chunk:280                break281 282            substrate += encodeFun(chunk, asn1Spec, **options)283            pos += maxChunkSize284 285        return substrate, True, True286 287 288class NullEncoder(AbstractItemEncoder):289    supportIndefLenMode = False290 291    def encodeValue(self, value, asn1Spec, encodeFun, **options):292        return b'', False, True293 294 295class ObjectIdentifierEncoder(AbstractItemEncoder):296    supportIndefLenMode = False297 298    def encodeValue(self, value, asn1Spec, encodeFun, **options):299        if asn1Spec is not None:300            value = asn1Spec.clone(value)301 302        oid = value.asTuple()303 304        # Build the first pair305        try:306            first = oid[0]307            second = oid[1]308 309        except IndexError:310            raise error.PyAsn1Error('Short OID %s' % (value,))311 312        if 0 <= second <= 39:313            if first == 1:314                oid = (second + 40,) + oid[2:]315            elif first == 0:316                oid = (second,) + oid[2:]317            elif first == 2:318                oid = (second + 80,) + oid[2:]319            else:320                raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))321 322        elif first == 2:323            oid = (second + 80,) + oid[2:]324 325        else:326            raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))327 328        octets = ()329 330        # Cycle through subIds331        for subOid in oid:332            if 0 <= subOid <= 127:333                # Optimize for the common case334                octets += (subOid,)335 336            elif subOid > 127:337                # Pack large Sub-Object IDs338                res = (subOid & 0x7f,)339                subOid >>= 7340 341                while subOid:342                    res = (0x80 | (subOid & 0x7f),) + res343                    subOid >>= 7344 345                # Add packed Sub-Object ID to resulted Object ID346                octets += res347 348            else:349                raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value))350 351        return octets, False, False352 353 354class RelativeOIDEncoder(AbstractItemEncoder):355    supportIndefLenMode = False356 357    def encodeValue(self, value, asn1Spec, encodeFun, **options):358        if asn1Spec is not None:359            value = asn1Spec.clone(value)360 361        octets = ()362 363        # Cycle through subIds364        for subOid in value.asTuple():365            if 0 <= subOid <= 127:366                # Optimize for the common case367                octets += (subOid,)368 369            elif subOid > 127:370                # Pack large Sub-Object IDs371                res = (subOid & 0x7f,)372                subOid >>= 7373 374                while subOid:375                    res = (0x80 | (subOid & 0x7f),) + res376                    subOid >>= 7377 378                # Add packed Sub-Object ID to resulted RELATIVE-OID379                octets += res380 381            else:382                raise error.PyAsn1Error('Negative RELATIVE-OID arc %s at %s' % (subOid, value))383 384        return octets, False, False385 386 387class RealEncoder(AbstractItemEncoder):388    supportIndefLenMode = False389    binEncBase = 2  # set to None to choose encoding base automatically390 391    @staticmethod392    def _dropFloatingPoint(m, encbase, e):393        ms, es = 1, 1394        if m < 0:395            ms = -1  # mantissa sign396 397        if e < 0:398            es = -1  # exponent sign399 400        m *= ms401 402        if encbase == 8:403            m *= 2 ** (abs(e) % 3 * es)404            e = abs(e) // 3 * es405 406        elif encbase == 16:407            m *= 2 ** (abs(e) % 4 * es)408            e = abs(e) // 4 * es409 410        while True:411            if int(m) != m:412                m *= encbase413                e -= 1414                continue415            break416 417        return ms, int(m), encbase, e418 419    def _chooseEncBase(self, value):420        m, b, e = value421        encBase = [2, 8, 16]422        if value.binEncBase in encBase:423            return self._dropFloatingPoint(m, value.binEncBase, e)424 425        elif self.binEncBase in encBase:426            return self._dropFloatingPoint(m, self.binEncBase, e)427 428        # auto choosing base 2/8/16429        mantissa = [m, m, m]430        exponent = [e, e, e]431        sign = 1432        encbase = 2433        e = float('inf')434 435        for i in range(3):436            (sign,437             mantissa[i],438             encBase[i],439             exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i])440 441            if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m):442                e = exponent[i]443                m = int(mantissa[i])444                encbase = encBase[i]445 446        if LOG:447            LOG('automatically chosen REAL encoding base %s, sign %s, mantissa %s, '448                'exponent %s' % (encbase, sign, m, e))449 450        return sign, m, encbase, e451 452    def encodeValue(self, value, asn1Spec, encodeFun, **options):453        if asn1Spec is not None:454            value = asn1Spec.clone(value)455 456        if value.isPlusInf:457            return (0x40,), False, False458 459        if value.isMinusInf:460            return (0x41,), False, False461 462        m, b, e = value463 464        if not m:465            return b'', False, True466 467        if b == 10:468            if LOG:469                LOG('encoding REAL into character form')470 471            return b'\x03%dE%s%d' % (m, e == 0 and b'+' or b'', e), False, True472 473        elif b == 2:474            fo = 0x80  # binary encoding475            ms, m, encbase, e = self._chooseEncBase(value)476 477            if ms < 0:  # mantissa sign478                fo |= 0x40  # sign bit479 480            # exponent & mantissa normalization481            if encbase == 2:482                while m & 0x1 == 0:483                    m >>= 1484                    e += 1485 486            elif encbase == 8:487                while m & 0x7 == 0:488                    m >>= 3489                    e += 1490                fo |= 0x10491 492            else:  # encbase = 16493                while m & 0xf == 0:494                    m >>= 4495                    e += 1496                fo |= 0x20497 498            sf = 0  # scale factor499 500            while m & 0x1 == 0:501                m >>= 1502                sf += 1503 504            if sf > 3:505                raise error.PyAsn1Error('Scale factor overflow')  # bug if raised506 507            fo |= sf << 2508            eo = b''509            if e == 0 or e == -1:510                eo = bytes((e & 0xff,))511 512            else:513                while e not in (0, -1):514                    eo = bytes((e & 0xff,)) + eo515                    e >>= 8516 517                if e == 0 and eo and eo[0] & 0x80:518                    eo = bytes((0,)) + eo519 520                if e == -1 and eo and not (eo[0] & 0x80):521                    eo = bytes((0xff,)) + eo522 523            n = len(eo)524            if n > 0xff:525                raise error.PyAsn1Error('Real exponent overflow')526 527            if n == 1:528                pass529 530            elif n == 2:531                fo |= 1532 533            elif n == 3:534                fo |= 2535 536            else:537                fo |= 3538                eo = bytes((n & 0xff,)) + eo539 540            po = b''541 542            while m:543                po = bytes((m & 0xff,)) + po544                m >>= 8545 546            substrate = bytes((fo,)) + eo + po547 548            return substrate, False, True549 550        else:551            raise error.PyAsn1Error('Prohibited Real base %s' % b)552 553 554class SequenceEncoder(AbstractItemEncoder):555    omitEmptyOptionals = False556 557    # TODO: handling three flavors of input is too much -- split over codecs558 559    def encodeValue(self, value, asn1Spec, encodeFun, **options):560 561        substrate = b''562 563        omitEmptyOptionals = options.get(564            'omitEmptyOptionals', self.omitEmptyOptionals)565 566        if LOG:567            LOG('%sencoding empty OPTIONAL components' % (568                    omitEmptyOptionals and 'not ' or ''))569 570        if asn1Spec is None:571            # instance of ASN.1 schema572            inconsistency = value.isInconsistent573            if inconsistency:574                raise error.PyAsn1Error(575                    f"ASN.1 object {value.__class__.__name__} is inconsistent")576 577            namedTypes = value.componentType578 579            for idx, component in enumerate(value.values()):580                if namedTypes:581                    namedType = namedTypes[idx]582 583                    if namedType.isOptional and not component.isValue:584                        if LOG:585                            LOG('not encoding OPTIONAL component %r' % (namedType,))586                        continue587 588                    if namedType.isDefaulted and component == namedType.asn1Object:589                        if LOG:590                            LOG('not encoding DEFAULT component %r' % (namedType,))591                        continue592 593                    if omitEmptyOptionals:594                        options.update(ifNotEmpty=namedType.isOptional)595 596                # wrap open type blob if needed597                if namedTypes and namedType.openType:598 599                    wrapType = namedType.asn1Object600 601                    if wrapType.typeId in (602                            univ.SetOf.typeId, univ.SequenceOf.typeId):603 604                        substrate += encodeFun(605                                component, asn1Spec,606                                **dict(options, wrapType=wrapType.componentType))607 608                    else:609                        chunk = encodeFun(component, asn1Spec, **options)610 611                        if wrapType.isSameTypeWith(component):612                            substrate += chunk613 614                        else:615                            substrate += encodeFun(chunk, wrapType, **options)616 617                            if LOG:618                                LOG('wrapped with wrap type %r' % (wrapType,))619 620                else:621                    substrate += encodeFun(component, asn1Spec, **options)622 623        else:624            # bare Python value + ASN.1 schema625            for idx, namedType in enumerate(asn1Spec.componentType.namedTypes):626 627                try:628                    component = value[namedType.name]629 630                except KeyError:631                    raise error.PyAsn1Error('Component name "%s" not found in %r' % (632                        namedType.name, value))633 634                if namedType.isOptional and namedType.name not in value:635                    if LOG:636                        LOG('not encoding OPTIONAL component %r' % (namedType,))637                    continue638 639                if namedType.isDefaulted and component == namedType.asn1Object:640                    if LOG:641                        LOG('not encoding DEFAULT component %r' % (namedType,))642                    continue643 644                if omitEmptyOptionals:645                    options.update(ifNotEmpty=namedType.isOptional)646 647                componentSpec = namedType.asn1Object648 649                # wrap open type blob if needed650                if namedType.openType:651 652                    if componentSpec.typeId in (653                            univ.SetOf.typeId, univ.SequenceOf.typeId):654 655                        substrate += encodeFun(656                                component, componentSpec,657                                **dict(options, wrapType=componentSpec.componentType))658 659                    else:660                        chunk = encodeFun(component, componentSpec, **options)661 662                        if componentSpec.isSameTypeWith(component):663                            substrate += chunk664 665                        else:666                            substrate += encodeFun(chunk, componentSpec, **options)667 668                            if LOG:669                                LOG('wrapped with wrap type %r' % (componentSpec,))670 671                else:672                    substrate += encodeFun(component, componentSpec, **options)673 674        return substrate, True, True675 676 677class SequenceOfEncoder(AbstractItemEncoder):678    def _encodeComponents(self, value, asn1Spec, encodeFun, **options):679 680        if asn1Spec is None:681            inconsistency = value.isInconsistent682            if inconsistency:683                raise error.PyAsn1Error(684                    f"ASN.1 object {value.__class__.__name__} is inconsistent")685 686        else:687            asn1Spec = asn1Spec.componentType688 689        chunks = []690 691        wrapType = options.pop('wrapType', None)692 693        for idx, component in enumerate(value):694            chunk = encodeFun(component, asn1Spec, **options)695 696            if (wrapType is not None and697                    not wrapType.isSameTypeWith(component)):698                # wrap encoded value with wrapper container (e.g. ANY)699                chunk = encodeFun(chunk, wrapType, **options)700 701                if LOG:702                    LOG('wrapped with wrap type %r' % (wrapType,))703 704            chunks.append(chunk)705 706        return chunks707 708    def encodeValue(self, value, asn1Spec, encodeFun, **options):709        chunks = self._encodeComponents(710            value, asn1Spec, encodeFun, **options)711 712        return b''.join(chunks), True, True713 714 715class ChoiceEncoder(AbstractItemEncoder):716    def encodeValue(self, value, asn1Spec, encodeFun, **options):717        if asn1Spec is None:718            component = value.getComponent()719        else:720            names = [namedType.name for namedType in asn1Spec.componentType.namedTypes721                     if namedType.name in value]722            if len(names) != 1:723                raise error.PyAsn1Error('%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value))724 725            name = names[0]726 727            component = value[name]728            asn1Spec = asn1Spec[name]729 730        return encodeFun(component, asn1Spec, **options), True, True731 732 733class AnyEncoder(OctetStringEncoder):734    def encodeValue(self, value, asn1Spec, encodeFun, **options):735        if asn1Spec is None:736            value = value.asOctets()737        elif not isinstance(value, bytes):738            value = asn1Spec.clone(value).asOctets()739 740        return value, not options.get('defMode', True), True741 742 743TAG_MAP = {744    eoo.endOfOctets.tagSet: EndOfOctetsEncoder(),745    univ.Boolean.tagSet: BooleanEncoder(),746    univ.Integer.tagSet: IntegerEncoder(),747    univ.BitString.tagSet: BitStringEncoder(),748    univ.OctetString.tagSet: OctetStringEncoder(),749    univ.Null.tagSet: NullEncoder(),750    univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),751    univ.RelativeOID.tagSet: RelativeOIDEncoder(),752    univ.Enumerated.tagSet: IntegerEncoder(),753    univ.Real.tagSet: RealEncoder(),754    # Sequence & Set have same tags as SequenceOf & SetOf755    univ.SequenceOf.tagSet: SequenceOfEncoder(),756    univ.SetOf.tagSet: SequenceOfEncoder(),757    univ.Choice.tagSet: ChoiceEncoder(),758    # character string types759    char.UTF8String.tagSet: OctetStringEncoder(),760    char.NumericString.tagSet: OctetStringEncoder(),761    char.PrintableString.tagSet: OctetStringEncoder(),762    char.TeletexString.tagSet: OctetStringEncoder(),763    char.VideotexString.tagSet: OctetStringEncoder(),764    char.IA5String.tagSet: OctetStringEncoder(),765    char.GraphicString.tagSet: OctetStringEncoder(),766    char.VisibleString.tagSet: OctetStringEncoder(),767    char.GeneralString.tagSet: OctetStringEncoder(),768    char.UniversalString.tagSet: OctetStringEncoder(),769    char.BMPString.tagSet: OctetStringEncoder(),770    # useful types771    useful.ObjectDescriptor.tagSet: OctetStringEncoder(),772    useful.GeneralizedTime.tagSet: OctetStringEncoder(),773    useful.UTCTime.tagSet: OctetStringEncoder()774}775 776# Put in ambiguous & non-ambiguous types for faster codec lookup777TYPE_MAP = {778    univ.Boolean.typeId: BooleanEncoder(),779    univ.Integer.typeId: IntegerEncoder(),780    univ.BitString.typeId: BitStringEncoder(),781    univ.OctetString.typeId: OctetStringEncoder(),782    univ.Null.typeId: NullEncoder(),783    univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),784    univ.RelativeOID.typeId: RelativeOIDEncoder(),785    univ.Enumerated.typeId: IntegerEncoder(),786    univ.Real.typeId: RealEncoder(),787    # Sequence & Set have same tags as SequenceOf & SetOf788    univ.Set.typeId: SequenceEncoder(),789    univ.SetOf.typeId: SequenceOfEncoder(),790    univ.Sequence.typeId: SequenceEncoder(),791    univ.SequenceOf.typeId: SequenceOfEncoder(),792    univ.Choice.typeId: ChoiceEncoder(),793    univ.Any.typeId: AnyEncoder(),794    # character string types795    char.UTF8String.typeId: OctetStringEncoder(),796    char.NumericString.typeId: OctetStringEncoder(),797    char.PrintableString.typeId: OctetStringEncoder(),798    char.TeletexString.typeId: OctetStringEncoder(),799    char.VideotexString.typeId: OctetStringEncoder(),800    char.IA5String.typeId: OctetStringEncoder(),801    char.GraphicString.typeId: OctetStringEncoder(),802    char.VisibleString.typeId: OctetStringEncoder(),803    char.GeneralString.typeId: OctetStringEncoder(),804    char.UniversalString.typeId: OctetStringEncoder(),805    char.BMPString.typeId: OctetStringEncoder(),806    # useful types807    useful.ObjectDescriptor.typeId: OctetStringEncoder(),808    useful.GeneralizedTime.typeId: OctetStringEncoder(),809    useful.UTCTime.typeId: OctetStringEncoder()810}811 812 813class SingleItemEncoder(object):814    fixedDefLengthMode = None815    fixedChunkSize = None816 817    TAG_MAP = TAG_MAP818    TYPE_MAP = TYPE_MAP819 820    def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):821        self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP822        self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP823 824    def __call__(self, value, asn1Spec=None, **options):825        try:826            if asn1Spec is None:827                typeId = value.typeId828            else:829                typeId = asn1Spec.typeId830 831        except AttributeError:832            raise error.PyAsn1Error('Value %r is not ASN.1 type instance '833                                    'and "asn1Spec" not given' % (value,))834 835        if LOG:836            LOG('encoder called in %sdef mode, chunk size %s for type %s, '837                'value:\n%s' % (not options.get('defMode', True) and 'in' or '',838                                options.get('maxChunkSize', 0),839                                asn1Spec is None and value.prettyPrintType() or840                                asn1Spec.prettyPrintType(), value))841 842        if self.fixedDefLengthMode is not None:843            options.update(defMode=self.fixedDefLengthMode)844 845        if self.fixedChunkSize is not None:846            options.update(maxChunkSize=self.fixedChunkSize)847 848        try:849            concreteEncoder = self._typeMap[typeId]850 851            if LOG:852                LOG('using value codec %s chosen by type ID '853                    '%s' % (concreteEncoder.__class__.__name__, typeId))854 855        except KeyError:856            if asn1Spec is None:857                tagSet = value.tagSet858            else:859                tagSet = asn1Spec.tagSet860 861            # use base type for codec lookup to recover untagged types862            baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)863 864            try:865                concreteEncoder = self._tagMap[baseTagSet]866 867            except KeyError:868                raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))869 870            if LOG:871                LOG('using value codec %s chosen by tagSet '872                    '%s' % (concreteEncoder.__class__.__name__, tagSet))873 874        substrate = concreteEncoder.encode(value, asn1Spec, self, **options)875 876        if LOG:877            LOG('codec %s built %s octets of substrate: %s\nencoder '878                'completed' % (concreteEncoder, len(substrate),879                               debug.hexdump(substrate)))880 881        return substrate882 883 884class Encoder(object):885    SINGLE_ITEM_ENCODER = SingleItemEncoder886 887    def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **options):888        self._singleItemEncoder = self.SINGLE_ITEM_ENCODER(889            tagMap=tagMap, typeMap=typeMap, **options890        )891 892    def __call__(self, pyObject, asn1Spec=None, **options):893        return self._singleItemEncoder(894            pyObject, asn1Spec=asn1Spec, **options)895 896 897#: Turns ASN.1 object into BER octet stream.898#:899#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)900#: walks all its components recursively and produces a BER octet stream.901#:902#: Parameters903#: ----------904#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)905#:     A Python or pyasn1 object to encode. If Python object is given, `asnSpec`906#:     parameter is required to guide the encoding process.907#:908#: Keyword Args909#: ------------910#: asn1Spec:911#:     Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative912#:913#: defMode: :py:class:`bool`914#:     If :obj:`False`, produces indefinite length encoding915#:916#: maxChunkSize: :py:class:`int`917#:     Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)918#:919#: Returns920#: -------921#: : :py:class:`bytes`922#:     Given ASN.1 object encoded into BER octetstream923#:924#: Raises925#: ------926#: ~pyasn1.error.PyAsn1Error927#:     On encoding errors928#:929#: Examples930#: --------931#: Encode Python value into BER with ASN.1 schema932#:933#: .. code-block:: pycon934#:935#:    >>> seq = SequenceOf(componentType=Integer())936#:    >>> encode([1, 2, 3], asn1Spec=seq)937#:    b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'938#:939#: Encode ASN.1 value object into BER940#:941#: .. code-block:: pycon942#:943#:    >>> seq = SequenceOf(componentType=Integer())944#:    >>> seq.extend([1, 2, 3])945#:    >>> encode(seq)946#:    b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'947#:948encode = Encoder()949 950def __getattr__(attr: str):951    if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):952        warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning, stacklevel=2)953        return globals()[newAttr]954    raise AttributeError(attr)955 
codekingpro/portable-devtools · Team Ai