]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/asn1: support set tag when unmarshaling.
authorAdam Langley <agl@golang.org>
Tue, 28 Jan 2014 19:12:25 +0000 (14:12 -0500)
committerAdam Langley <agl@golang.org>
Tue, 28 Jan 2014 19:12:25 +0000 (14:12 -0500)
This change also addresses some places where the comments were lacking.

Fixes #7087.

LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/56700043

src/pkg/encoding/asn1/asn1.go
src/pkg/encoding/asn1/asn1_test.go
src/pkg/encoding/asn1/marshal.go

index dfcbf920d0afcd34783582fb4be4b9326552e81d..b8a732e0244c85654189cd30b0e9386d42f75d31 100644 (file)
@@ -634,6 +634,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                universalTag = tagGeneralizedTime
        }
 
+       if params.set {
+               universalTag = tagSet
+       }
+
        expectedClass := classUniversal
        expectedTag := universalTag
 
@@ -854,13 +858,20 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
 //
 // The following tags on struct fields have special meaning to Unmarshal:
 //
-//     optional                marks the field as ASN.1 OPTIONAL
-//     [explicit] tag:x        specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
-//     default:x               sets the default value for optional integer fields
+//     application     specifies that a APPLICATION tag is used
+//     default:x       sets the default value for optional integer fields
+//     explicit        specifies that an additional, explicit tag wraps the implicit one
+//     optional        marks the field as ASN.1 OPTIONAL
+//     set             causes a SET, rather than a SEQUENCE type to be expected
+//     tag:x           specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
 //
 // If the type of the first field of a structure is RawContent then the raw
 // ASN1 contents of the struct will be stored in it.
 //
+// If the type name of a slice element ends with "SET" then it's treated as if
+// the "set" tag was set on it. This can be used with nested slices where a
+// struct tag cannot be given.
+//
 // 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 error) {
index ea98e023faf20badfec5caa5f0cc2f8411f5957d..4f60b6751dfeea72fcfa4c505742a62e61415b79 100644 (file)
@@ -397,6 +397,10 @@ type TestBigInt struct {
        X *big.Int
 }
 
+type TestSet struct {
+       Ints []int `asn1:"set"`
+}
+
 var unmarshalTestData = []struct {
        in  []byte
        out interface{}
@@ -416,6 +420,7 @@ var unmarshalTestData = []struct {
        {[]byte{0x01, 0x01, 0xff}, newBool(true)},
        {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
        {[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
+       {[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}},
 }
 
 func TestUnmarshal(t *testing.T) {
index ed17e41a55cfd9f5d1e6ac9f703520eecb597db1..da50cf25e83a7ab5c38a3ed2d3dc6005bf9d780c 100644 (file)
@@ -568,6 +568,14 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 }
 
 // Marshal returns the ASN.1 encoding of val.
+//
+// In addition to the struct tags recognised by Unmarshal, the following can be
+// used:
+//
+//     ia5:            causes strings to be marshaled as ASN.1, IA5 strings
+//     omitempty:      causes empty slices to be skipped
+//     printable:      causes strings to be marshaled as ASN.1, PrintableString strings.
+//     utf8:           causes strings to be marshaled as ASN.1, UTF8 strings
 func Marshal(val interface{}) ([]byte, error) {
        var out bytes.Buffer
        v := reflect.ValueOf(val)