0 +ˆl–Ðz¾”Ši?u‰@†àž¸”Å£À ƒ}ÆZ_‡I|¥ŠèªÀÇ%¢ PyASN1 Constructed types

1.3 PyASN1 Constructed types

Besides scalar types, ASN.1 specifies so-called constructed ones - these are capable of holding one or more values of other types, both scalar and constructed.

In pyasn1 implementation, constructed ASN.1 types behave like Python sequences, and also support additional component addressing methods, specific to particular constructed type.

1.3.1 Sequence and Set types

The Sequence and Set types have many similar properties:

  • they can hold any number of inner components of different types
  • every component has a human-friendly identifier
  • any component can have a default value
  • some components can be absent.

However, Sequence type guarantees the ordering of Sequence value components to match their declaration order. By contrast, components of the Set type can be ordered to best suite application's needs.

Record ::= SEQUENCE {
  id        INTEGER,
  room  [0] INTEGER OPTIONAL,
  house [1] INTEGER DEFAULT 0
}

Up to this moment, the only method we used for creating new pyasn1 types is Python sub-classing. With this method, a new, named Python class is created what mimics type derivation in ASN.1 grammar. However, ASN.1 also allows for defining anonymous subtypes (room and house components in the example above). To support anonymous subtyping in pyasn1, a cloning operation on an existing pyasn1 type object can be invoked what creates a new instance of original object with possibly modified properties.

>>> from pyasn1.type import univ, namedtype, tag
>>> class Record(univ.Sequence):
...   componentType = namedtype.NamedTypes(
...     namedtype.NamedType('id', univ.Integer()),
...     namedtype.OptionalNamedType(
...       'room',
...       univ.Integer().subtype(
...         implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)
...       )
...     ),
...     namedtype.DefaultedNamedType(
...       'house', 
...       univ.Integer(0).subtype(
...         implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)
...       )
...     )
...   )
>>>

All pyasn1 constructed type classes have a class attribute componentType that represent default type specification. Its value is a NamedTypes object.

The NamedTypes class instance holds a sequence of NameType, OptionalNamedType or DefaultedNamedType objects which, in turn, refer to pyasn1 type objects that represent inner SEQUENCE components specification.

Finally, invocation of a subtype() method of pyasn1 type objects in the code above returns an implicitly tagged copy of original object.

Once a SEQUENCE or SET type is decleared with pyasn1, it can be instantiated and initialized (continuing the above code):

>>> record = Record()
>>> record.setComponentByName('id', 123)
>>> print(record.prettyPrint())
Record:
 id=123
>>> 
>>> record.setComponentByPosition(1, 321)
>>> print(record.prettyPrint())
Record:
 id=123
 room=321
>>>
>>> record.setDefaultComponents()
>>> print(record.prettyPrint())
Record:
 id=123
 room=321
 house=0

Inner components of pyasn1 Sequence/Set objects could be accessed using the following methods:

>>> record.getComponentByName('id')
Integer(123)
>>> record.getComponentByPosition(1)
Integer(321)
>>> record[2]
Integer(0)
>>> for idx in range(len(record)):
...   print(record.getNameByPosition(idx), record.getComponentByPosition(idx))
id 123
room 321
house 0
>>>

The Set type share all the properties of Sequence type, and additionally s