if err != nil {
return
}
+ // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so
+ // that a sequence of them can be parsed into a []string.
+ if t.tag == tagGeneralString {
+ t.tag = tagPrintableString
+ }
if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
err = StructuralError{"sequence tag mismatch"}
return
return
}
if params.explicit {
- if t.class == classContextSpecific && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
+ expectedClass := classContextSpecific
+ if params.application {
+ expectedClass = classApplication
+ }
+ if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
if t.length > 0 {
t, offset, err = parseTagAndLength(bytes, offset)
if err != nil {
if universalTag == tagPrintableString && t.tag == tagIA5String {
universalTag = tagIA5String
}
+ // Likewise for GeneralString
+ if universalTag == tagPrintableString && t.tag == tagGeneralString {
+ universalTag = tagGeneralString
+ }
// Special case for time: UTCTime and GeneralizedTime both map to the
// Go type time.Time.
expectedTag = *params.tag
}
+ if !params.explicit && params.application && params.tag != nil {
+ expectedClass = classApplication
+ expectedTag = *params.tag
+ }
+
// We have unwrapped any explicit tagging at this point.
if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType {
// Tags don't match. Again, it could be an optional element.
v, err = parseIA5String(innerBytes)
case tagT61String:
v, err = parseT61String(innerBytes)
+ case tagGeneralString:
+ // GeneralString is specified in ISO-2022/ECMA-35,
+ // A brief review suggests that it includes structures
+ // that allow the encoding to change midstring and
+ // such. We give up and pass it as an 8-bit string.
+ v, err = parseT61String(innerBytes)
default:
err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
}
// Other ASN.1 types are not supported; if it encounters them,
// Unmarshal returns a parse error.
func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
+ return UnmarshalWithParams(b, val, "")
+}
+
+// UnmarshalWithParams allows field parameters to be specified for the
+// top-level element. The form of the params is the same as the field tags.
+func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
v := reflect.NewValue(val).(*reflect.PtrValue).Elem()
- offset, err := parseField(v, b, 0, fieldParameters{})
+ offset, err := parseField(v, b, 0, parseFieldParameters(params))
if err != nil {
return nil, err
}