Structured types are based on simple types or any subtype derived from them. The term for a single entity of a structure is component. The number of possible structured types is infinite, althoug there is just small finite set of operations to construct them. There are structured types constructed by simple collecting components of the same or different types, these collection can be ordered or not. Then there are structured types constructed by choosing from finite set of components. And, last but not least, special type representing any type. Here are the keywords, as usual spelling out their function in English:
Sometimes it is useful to include components, which will not appear in structure each time it is used. They are usually called optional components and ASN.1 provides you with construction for them with keyword OPTIONAL. Let's have a protocol which may or may not use check sum. It can be then defined as:
Protocol ::= SEQUENCE {
destination Reference,
data OCTET STRING,
checkSum CheckSum OPTIONAL
}
On the other hand, there are situations, when components must be present, but are not assigned a value on transmitting side, but examined on receiving side. It would be useful to set it to some neutral default value. ASN.1 allows doing that by including a DEFAULT clause to definition of component. Here is another example, that uses both optional and default values:
Protocol ::= SEQUENCE {
sequenceNumber INTEGER,
subSequenceNumber INTEGER DEFAULT 0,
flowControl FlowControlConfirm OPTIONAL
}
It is also possible that a single component of structure is a whole structure itsef. Then a nested structure is built this way. But it is also possible to include only components of a given structure by using keyword COMPONENTS OF.
Typ1 ::= SET {
f INTEGER,
g BOOLEAN
}
Typ2 ::= SET {
e REAL,
COMPONENTS OF Typ1
}
The keyword COMPONENT OF itself is not a component, thus has not has an identifier. Then it is natural that only structure of the same type can become a donor of components (i.e. you cannot combine e.g. set with components of sequence and vice versa). This construct has also drawback in ensuring distinct names although when using tags and possibility of endless loop when recursed.
Probably the only useful metod for subtyping structures is inner subtyping. It is the method to derive a subtype by conditional extracting components form parent type. Let's have a structure
ExpeditedDataAcknowledgement ::= SET {
destRef Reference,
yr2nr TPDUnumber,
checkSum CheckSum OPTIONAL
}
TPDUnumber ::= INTEGER (0 .. 2147483647)
Then it is possible to derive a subtype by restricting this structure to componet yr2nr to range (0..127) and absence of check sum:
NormalEA ::= ExpeditedDataAcknowledgement (
WITH COMPONENTS {
destRef,
zr2nr (0..127)
}
)
This is an example written by full specification, i.e. enumerating all parent components. Another way to type the same is using partial specification, where only components affecting choice criteria are enumerated:
NormalEA ::= ExpeditedDataAcknowledgement (
WITH COMPONENTS {...,
zr2nr (0..127),
checkSum ABSENT
}
)
Partial specification begins with special keyword '{...,' and uses ABSENT and PRESENT keywords to specify necessity of component absence or presention.
Both full and partial specifications can be used, usage depends only on your taste and/or conveniences. It is usually better to higher readability to use partial specification when subtyping on a small set of components to focus on this set only, unless almost all components are affected.