Index: third_party/gsutil/third_party/pyasn1/doc/codecs.html |
diff --git a/third_party/gsutil/third_party/pyasn1/doc/codecs.html b/third_party/gsutil/third_party/pyasn1/doc/codecs.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9c2c36ed6f053a16bbdf271e217714d9ba4a1962 |
--- /dev/null |
+++ b/third_party/gsutil/third_party/pyasn1/doc/codecs.html |
@@ -0,0 +1,503 @@ |
+<html> |
+<title> |
+PyASN1 codecs |
+</title> |
+<head> |
+</head> |
+<body> |
+<center> |
+<table width=60%> |
+<tr> |
+<td> |
+<h3> |
+2. PyASN1 Codecs |
+</h3> |
+ |
+<p> |
+In ASN.1 context, |
+<a href=http://en.wikipedia.org/wiki/Codec>codec</a> |
+is a program that transforms between concrete data structures and a stream |
+of octets, suitable for transmission over the wire. This serialized form of |
+data is sometimes called <i>substrate</i> or <i>essence</i>. |
+</p> |
+ |
+<p> |
+In pyasn1 implementation, substrate takes shape of Python 3 bytes or |
+Python 2 string objects. |
+</p> |
+ |
+<p> |
+One of the properties of a codec is its ability to cope with incomplete |
+data and/or substrate what implies codec to be stateful. In other words, |
+when decoder runs out of substrate and data item being recovered is still |
+incomplete, stateful codec would suspend and complete data item recovery |
+whenever the rest of substrate becomes available. Similarly, stateful encoder |
+would encode data items in multiple steps waiting for source data to |
+arrive. Codec restartability is especially important when application deals |
+with large volumes of data and/or runs on low RAM. For an interesting |
+discussion on codecs options and design choices, refer to |
+<a href=http://directory.apache.org/subprojects/asn1/>Apache ASN.1 project</a> |
+. |
+</p> |
+ |
+<p> |
+As of this writing, codecs implemented in pyasn1 are all stateless, mostly |
+to keep the code simple. |
+</p> |
+ |
+<p> |
+The pyasn1 package currently supports |
+<a href=http://en.wikipedia.org/wiki/Basic_encoding_rules>BER</a> codec and |
+its variations -- |
+<a href=http://en.wikipedia.org/wiki/Canonical_encoding_rules>CER</a> and |
+<a href=http://en.wikipedia.org/wiki/Distinguished_encoding_rules>DER</a>. |
+More ASN.1 codecs are planned for implementation in the future. |
+</p> |
+ |
+<a name="2.1"></a> |
+<h4> |
+2.1 Encoders |
+</h4> |
+ |
+<p> |
+Encoder is used for transforming pyasn1 value objects into substrate. Only |
+pyasn1 value objects could be serialized, attempts to process pyasn1 type |
+objects will cause encoder failure. |
+</p> |
+ |
+<p> |
+The following code will create a pyasn1 Integer object and serialize it with |
+BER encoder: |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder |
+>>> encoder.encode(univ.Integer(123456)) |
+b'\x02\x03\x01\xe2@' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+BER standard also defines a so-called <i>indefinite length</i> encoding form |
+which makes large data items processing more memory efficient. It is mostly |
+useful when encoder does not have the whole value all at once and the |
+length of the value can not be determined at the beginning of encoding. |
+</p> |
+ |
+<p> |
+<i>Constructed encoding</i> is another feature of BER closely related to the |
+indefinite length form. In essence, a large scalar value (such as ASN.1 |
+character BitString type) could be chopped into smaller chunks by encoder |
+and transmitted incrementally to limit memory consumption. Unlike indefinite |
+length case, the length of the whole value must be known in advance when |
+using constructed, definite length encoding form. |
+</p> |
+ |
+<p> |
+Since pyasn1 codecs are not restartable, pyasn1 encoder may only encode data |
+item all at once. However, even in this case, generating indefinite length |
+encoding may help a low-memory receiver, running a restartable decoder, |
+to process a large data item. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder |
+>>> encoder.encode( |
+... univ.OctetString('The quick brown fox jumps over the lazy dog'), |
+... defMode=False, |
+... maxChunkSize=8 |
+... ) |
+b'$\x80\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \ |
+t\x04\x08he lazy \x04\x03dog\x00\x00' |
+>>> |
+>>> encoder.encode( |
+... univ.OctetString('The quick brown fox jumps over the lazy dog'), |
+... maxChunkSize=8 |
+... ) |
+b'$7\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \ |
+t\x04\x08he lazy \x04\x03dog' |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+The <b>defMode</b> encoder parameter disables definite length encoding mode, |
+while the optional <b>maxChunkSize</b> parameter specifies desired |
+substrate chunk size that influences memory requirements at the decoder's end. |
+</p> |
+ |
+<p> |
+To use CER or DER encoders one needs to explicitly import and call them - the |
+APIs are all compatible. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder as ber_encoder |
+>>> from pyasn1.codec.cer import encoder as cer_encoder |
+>>> from pyasn1.codec.der import encoder as der_encoder |
+>>> ber_encoder.encode(univ.Boolean(True)) |
+b'\x01\x01\x01' |
+>>> cer_encoder.encode(univ.Boolean(True)) |
+b'\x01\x01\xff' |
+>>> der_encoder.encode(univ.Boolean(True)) |
+b'\x01\x01\xff' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<a name="2.2"></a> |
+<h4> |
+2.2 Decoders |
+</h4> |
+ |
+<p> |
+In the process of decoding, pyasn1 value objects are created and linked to |
+each other, based on the information containted in the substrate. Thus, |
+the original pyasn1 value object(s) are recovered. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> substrate = encoder.encode(univ.Boolean(True)) |
+>>> decoder.decode(substrate) |
+(Boolean('True(1)'), b'') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Commenting on the code snippet above, pyasn1 decoder accepts substrate |
+as an argument and returns a tuple of pyasn1 value object (possibly |
+a top-level one in case of constructed object) and unprocessed part |
+of input substrate. |
+</p> |
+ |
+<p> |
+All pyasn1 decoders can handle both definite and indefinite length |
+encoding modes automatically, explicit switching into one mode |
+to another is not required. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> substrate = encoder.encode( |
+... univ.OctetString('The quick brown fox jumps over the lazy dog'), |
+... defMode=False, |
+... maxChunkSize=8 |
+... ) |
+>>> decoder.decode(substrate) |
+(OctetString(b'The quick brown fox jumps over the lazy dog'), b'') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Speaking of BER/CER/DER encoding, in many situations substrate may not contain |
+all necessary information needed for complete and accurate ASN.1 values |
+recovery. The most obvious cases include implicitly tagged ASN.1 types |
+and constrained types. |
+</p> |
+ |
+<p> |
+As discussed earlier in this handbook, when an ASN.1 type is implicitly |
+tagged, previous outermost tag is lost and never appears in substrate. |
+If it is the base tag that gets lost, decoder is unable to pick type-specific |
+value decoder at its table of built-in types, and therefore recover |
+the value part, based only on the information contained in substrate. The |
+approach taken by pyasn1 decoder is to use a prototype pyasn1 type object (or |
+a set of them) to <i>guide</i> the decoding process by matching [possibly |
+incomplete] tags recovered from substrate with those found in prototype pyasn1 |
+type objects (also called pyasn1 specification object further in this paper). |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.codec.ber import decoder |
+>>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer()) |
+Integer(12), b'' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Decoder would neither modify pyasn1 specification object nor use |
+its current values (if it's a pyasn1 value object), but rather use it as |
+a hint for choosing proper decoder and as a pattern for creating new objects: |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ, tag |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> i = univ.Integer(12345).subtype( |
+... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) |
+... ) |
+>>> substrate = encoder.encode(i) |
+>>> substrate |
+b'\x9f(\x0209' |
+>>> decoder.decode(substrate) |
+Traceback (most recent call last): |
+... |
+pyasn1.error.PyAsn1Error: |
+ TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec |
+>>> decoder.decode(substrate, asn1Spec=i) |
+(Integer(12345), b'') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Notice in the example above, that an attempt to run decoder without passing |
+pyasn1 specification object fails because recovered tag does not belong |
+to any of the built-in types. |
+</p> |
+ |
+<p> |
+Another important feature of guided decoder operation is the use of |
+values constraints possibly present in pyasn1 specification object. |
+To explain this, we will decode a random integer object into generic Integer |
+and the constrained one. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ, constraint |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> class DialDigit(univ.Integer): |
+... subtypeSpec = constraint.ValueRangeConstraint(0,9) |
+>>> substrate = encoder.encode(univ.Integer(13)) |
+>>> decoder.decode(substrate) |
+(Integer(13), b'') |
+>>> decoder.decode(substrate, asn1Spec=DialDigit()) |
+Traceback (most recent call last): |
+... |
+pyasn1.type.error.ValueConstraintError: |
+ ValueRangeConstraint(0, 9) failed at: 13 |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Similarily to encoders, to use CER or DER decoders application has to |
+explicitly import and call them - all APIs are compatible. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder as ber_encoder |
+>>> substrate = ber_encoder.encode(univ.OctetString('http://pyasn1.sf.net')) |
+>>> |
+>>> from pyasn1.codec.ber import decoder as ber_decoder |
+>>> from pyasn1.codec.cer import decoder as cer_decoder |
+>>> from pyasn1.codec.der import decoder as der_decoder |
+>>> |
+>>> ber_decoder.decode(substrate) |
+(OctetString(b'http://pyasn1.sf.net'), b'') |
+>>> cer_decoder.decode(substrate) |
+(OctetString(b'http://pyasn1.sf.net'), b'') |
+>>> der_decoder.decode(substrate) |
+(OctetString(b'http://pyasn1.sf.net'), b'') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<a name="2.2.1"></a> |
+<h4> |
+2.2.1 Decoding untagged types |
+</h4> |
+ |
+<p> |
+It has already been mentioned, that ASN.1 has two "special case" types: |
+CHOICE and ANY. They are different from other types in part of |
+tagging - unless these two are additionally tagged, neither of them will |
+have their own tag. Therefore these types become invisible in substrate |
+and can not be recovered without passing pyasn1 specification object to |
+decoder. |
+</p> |
+ |
+<p> |
+To explain the issue, we will first prepare a Choice object to deal with: |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ, namedtype |
+>>> class CodeOrMessage(univ.Choice): |
+... componentType = namedtype.NamedTypes( |
+... namedtype.NamedType('code', univ.Integer()), |
+... namedtype.NamedType('message', univ.OctetString()) |
+... ) |
+>>> |
+>>> codeOrMessage = CodeOrMessage() |
+>>> codeOrMessage.setComponentByName('message', 'my string value') |
+>>> print(codeOrMessage.prettyPrint()) |
+CodeOrMessage: |
+ message=b'my string value' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Let's now encode this Choice object and then decode its substrate |
+with and without pyasn1 specification object: |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> substrate = encoder.encode(codeOrMessage) |
+>>> substrate |
+b'\x04\x0fmy string value' |
+>>> encoder.encode(univ.OctetString('my string value')) |
+b'\x04\x0fmy string value' |
+>>> |
+>>> decoder.decode(substrate) |
+(OctetString(b'my string value'), b'') |
+>>> codeOrMessage, substrate = decoder.decode(substrate, asn1Spec=CodeOrMessage()) |
+>>> print(codeOrMessage.prettyPrint()) |
+CodeOrMessage: |
+ message=b'my string value' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+First thing to notice in the listing above is that the substrate produced |
+for our Choice value object is equivalent to the substrate for an OctetString |
+object initialized to the same value. In other words, any information about |
+the Choice component is absent in encoding. |
+</p> |
+ |
+<p> |
+Sure enough, that kind of substrate will decode into an OctetString object, |
+unless original Choice type object is passed to decoder to guide the decoding |
+process. |
+</p> |
+ |
+<p> |
+Similarily untagged ANY type behaves differently on decoding phase - when |
+decoder bumps into an Any object in pyasn1 specification, it stops decoding |
+and puts all the substrate into a new Any value object in form of an octet |
+string. Concerned application could then re-run decoder with an additional, |
+more exact pyasn1 specification object to recover the contents of Any |
+object. |
+</p> |
+ |
+<p> |
+As it was mentioned elsewhere in this paper, Any type allows for incomplete |
+or changing ASN.1 specification to be handled gracefully by decoder and |
+applications. |
+</p> |
+ |
+<p> |
+To illustrate the working of Any type, we'll have to make the stage |
+by encoding a pyasn1 object and then putting its substrate into an any |
+object. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> innerSubstrate = encoder.encode(univ.Integer(1234)) |
+>>> innerSubstrate |
+b'\x02\x02\x04\xd2' |
+>>> any = univ.Any(innerSubstrate) |
+>>> any |
+Any(b'\x02\x02\x04\xd2') |
+>>> substrate = encoder.encode(any) |
+>>> substrate |
+b'\x02\x02\x04\xd2' |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+As with Choice type encoding, there is no traces of Any type in substrate. |
+Obviously, the substrate we are dealing with, will decode into the inner |
+[Integer] component, unless pyasn1 specification is given to guide the |
+decoder. Continuing previous code: |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ |
+>>> from pyasn1.codec.ber import encoder, decoder |
+ |
+>>> decoder.decode(substrate) |
+(Integer(1234), b'') |
+>>> any, substrate = decoder.decode(substrate, asn1Spec=univ.Any()) |
+>>> any |
+Any(b'\x02\x02\x04\xd2') |
+>>> decoder.decode(str(any)) |
+(Integer(1234), b'') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+Both CHOICE and ANY types are widely used in practice. Reader is welcome to |
+take a look at |
+<a href=http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt> |
+ASN.1 specifications of X.509 applications</a> for more information. |
+</p> |
+ |
+<a name="2.2.2"></a> |
+<h4> |
+2.2.2 Ignoring unknown types |
+</h4> |
+ |
+<p> |
+When dealing with a loosely specified ASN.1 structure, the receiving |
+end may not be aware of some types present in the substrate. It may be |
+convenient then to turn decoder into a recovery mode. Whilst there, decoder |
+will not bail out when hit an unknown tag but rather treat it as an Any |
+type. |
+</p> |
+ |
+<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
+<pre> |
+>>> from pyasn1.type import univ, tag |
+>>> from pyasn1.codec.ber import encoder, decoder |
+>>> taggedInt = univ.Integer(12345).subtype( |
+... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) |
+... ) |
+>>> substrate = encoder.encode(taggedInt) |
+>>> decoder.decode(substrate) |
+Traceback (most recent call last): |
+... |
+pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec |
+>>> |
+>>> decoder.decode.defaultErrorState = decoder.stDumpRawValue |
+>>> decoder.decode(substrate) |
+(Any(b'\x9f(\x0209'), '') |
+>>> |
+</pre> |
+</td></tr></table> |
+ |
+<p> |
+It's also possible to configure a custom decoder, to handle unknown tags |
+found in substrate. This can be done by means of <b>defaultRawDecoder</b> |
+attribute holding a reference to type decoder object. Refer to the source |
+for API details. |
+</p> |
+ |
+<hr> |
+ |
+</td> |
+</tr> |
+</table> |
+</center> |
+</body> |
+</html> |