Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package asn1

import (
	
	
	
)
ASN.1 objects have metadata preceding them: the tag: the type of the object a flag denoting if this object is compound or not the class type: the namespace of the tag the length of the object, in bytes
Here are some standard tags and classes
ASN.1 tags represent the type of the following object.
ASN.1 class types represent the namespace of the tag.
ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead of" and "in addition to". When not specified, every primitive type has a default tag in the UNIVERSAL class. For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1 doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT CONTEXT-SPECIFIC 42], that means that the tag is replaced by another. On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an /additional/ tag would wrap the default tag. This explicit tag will have the compound flag set. (This is used in order to remove ambiguity with optional elements.) You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we don't support that here. We support a single layer of EXPLICIT or IMPLICIT tagging with tag strings on the fields of a structure.
fieldParameters is the parsed representation of tag string from a structure field.
type fieldParameters struct {
	optional     bool   // true iff the field is OPTIONAL
	explicit     bool   // true iff an EXPLICIT tag is in use.
	application  bool   // true iff an APPLICATION tag is in use.
	private      bool   // true iff a PRIVATE tag is in use.
	defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
	tag          *int   // the EXPLICIT or IMPLICIT tag (maybe nil).
	stringType   int    // the string tag to use when marshaling.
	timeType     int    // the time tag to use when marshaling.
	set          bool   // true iff this should be encoded as a SET
	omitEmpty    bool   // true iff this should be omitted if empty when marshaling.
Invariants: if explicit is set, tag is non-nil.
}
Given a tag string with the format specified in the package comment, parseFieldParameters will parse it into a fieldParameters structure, ignoring unknown parts of the string.
This loop uses IndexByte and explicit slicing instead of strings.Split(str, ",") to reduce allocations.
		 := strings.IndexByte(, ',')
		if  < 0 {
			,  = , ""
		} else {
			,  = [:], [+1:]
		}
		switch {
		case  == "optional":
			.optional = true
		case  == "explicit":
			.explicit = true
			if .tag == nil {
				.tag = new(int)
			}
		case  == "generalized":
			.timeType = TagGeneralizedTime
		case  == "utc":
			.timeType = TagUTCTime
		case  == "ia5":
			.stringType = TagIA5String
		case  == "printable":
			.stringType = TagPrintableString
		case  == "numeric":
			.stringType = TagNumericString
		case  == "utf8":
			.stringType = TagUTF8String
		case strings.HasPrefix(, "default:"):
			,  := strconv.ParseInt([8:], 10, 64)
			if  == nil {
				.defaultValue = new(int64)
				*.defaultValue = 
			}
		case strings.HasPrefix(, "tag:"):
			,  := strconv.Atoi([4:])
			if  == nil {
				.tag = new(int)
				*.tag = 
			}
		case  == "set":
			.set = true
		case  == "application":
			.application = true
			if .tag == nil {
				.tag = new(int)
			}
		case  == "private":
			.private = true
			if .tag == nil {
				.tag = new(int)
			}
		case  == "omitempty":
			.omitEmpty = true
		}
	}
	return
}
Given a reflected Go type, getUniversalType returns the default tag number and expected compound flag.
func ( reflect.Type) ( bool,  int, ,  bool) {
	switch  {
	case rawValueType:
		return true, -1, false, true
	case objectIdentifierType:
		return false, TagOID, false, true
	case bitStringType:
		return false, TagBitString, false, true
	case timeType:
		return false, TagUTCTime, false, true
	case enumeratedType:
		return false, TagEnum, false, true
	case bigIntType:
		return false, TagInteger, false, true
	}
	switch .Kind() {
	case reflect.Bool:
		return false, TagBoolean, false, true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return false, TagInteger, false, true
	case reflect.Struct:
		return false, TagSequence, true, true
	case reflect.Slice:
		if .Elem().Kind() == reflect.Uint8 {
			return false, TagOctetString, false, true
		}
		if strings.HasSuffix(.Name(), "SET") {
			return false, TagSet, true, true
		}
		return false, TagSequence, true, true
	case reflect.String:
		return false, TagPrintableString, false, true
	}
	return false, 0, false, false