libgo: Update to Go 1.3 release.
[official-gcc.git] / libgo / go / encoding / asn1 / marshal.go
blobe26fe59b305b29e1c8f81a06a61b150e3adb7ddb
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package asn1
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "math/big"
13 "reflect"
14 "time"
15 "unicode/utf8"
18 // A forkableWriter is an in-memory buffer that can be
19 // 'forked' to create new forkableWriters that bracket the
20 // original. After
21 // pre, post := w.fork();
22 // the overall sequence of bytes represented is logically w+pre+post.
23 type forkableWriter struct {
24 *bytes.Buffer
25 pre, post *forkableWriter
28 func newForkableWriter() *forkableWriter {
29 return &forkableWriter{new(bytes.Buffer), nil, nil}
32 func (f *forkableWriter) fork() (pre, post *forkableWriter) {
33 if f.pre != nil || f.post != nil {
34 panic("have already forked")
36 f.pre = newForkableWriter()
37 f.post = newForkableWriter()
38 return f.pre, f.post
41 func (f *forkableWriter) Len() (l int) {
42 l += f.Buffer.Len()
43 if f.pre != nil {
44 l += f.pre.Len()
46 if f.post != nil {
47 l += f.post.Len()
49 return
52 func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
53 n, err = out.Write(f.Bytes())
54 if err != nil {
55 return
58 var nn int
60 if f.pre != nil {
61 nn, err = f.pre.writeTo(out)
62 n += nn
63 if err != nil {
64 return
68 if f.post != nil {
69 nn, err = f.post.writeTo(out)
70 n += nn
72 return
75 func marshalBase128Int(out *forkableWriter, n int64) (err error) {
76 if n == 0 {
77 err = out.WriteByte(0)
78 return
81 l := 0
82 for i := n; i > 0; i >>= 7 {
83 l++
86 for i := l - 1; i >= 0; i-- {
87 o := byte(n >> uint(i*7))
88 o &= 0x7f
89 if i != 0 {
90 o |= 0x80
92 err = out.WriteByte(o)
93 if err != nil {
94 return
98 return nil
101 func marshalInt64(out *forkableWriter, i int64) (err error) {
102 n := int64Length(i)
104 for ; n > 0; n-- {
105 err = out.WriteByte(byte(i >> uint((n-1)*8)))
106 if err != nil {
107 return
111 return nil
114 func int64Length(i int64) (numBytes int) {
115 numBytes = 1
117 for i > 127 {
118 numBytes++
119 i >>= 8
122 for i < -128 {
123 numBytes++
124 i >>= 8
127 return
130 func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
131 if n.Sign() < 0 {
132 // A negative number has to be converted to two's-complement
133 // form. So we'll subtract 1 and invert. If the
134 // most-significant-bit isn't set then we'll need to pad the
135 // beginning with 0xff in order to keep the number negative.
136 nMinus1 := new(big.Int).Neg(n)
137 nMinus1.Sub(nMinus1, bigOne)
138 bytes := nMinus1.Bytes()
139 for i := range bytes {
140 bytes[i] ^= 0xff
142 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
143 err = out.WriteByte(0xff)
144 if err != nil {
145 return
148 _, err = out.Write(bytes)
149 } else if n.Sign() == 0 {
150 // Zero is written as a single 0 zero rather than no bytes.
151 err = out.WriteByte(0x00)
152 } else {
153 bytes := n.Bytes()
154 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
155 // We'll have to pad this with 0x00 in order to stop it
156 // looking like a negative number.
157 err = out.WriteByte(0)
158 if err != nil {
159 return
162 _, err = out.Write(bytes)
164 return
167 func marshalLength(out *forkableWriter, i int) (err error) {
168 n := lengthLength(i)
170 for ; n > 0; n-- {
171 err = out.WriteByte(byte(i >> uint((n-1)*8)))
172 if err != nil {
173 return
177 return nil
180 func lengthLength(i int) (numBytes int) {
181 numBytes = 1
182 for i > 255 {
183 numBytes++
184 i >>= 8
186 return
189 func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
190 b := uint8(t.class) << 6
191 if t.isCompound {
192 b |= 0x20
194 if t.tag >= 31 {
195 b |= 0x1f
196 err = out.WriteByte(b)
197 if err != nil {
198 return
200 err = marshalBase128Int(out, int64(t.tag))
201 if err != nil {
202 return
204 } else {
205 b |= uint8(t.tag)
206 err = out.WriteByte(b)
207 if err != nil {
208 return
212 if t.length >= 128 {
213 l := lengthLength(t.length)
214 err = out.WriteByte(0x80 | byte(l))
215 if err != nil {
216 return
218 err = marshalLength(out, t.length)
219 if err != nil {
220 return
222 } else {
223 err = out.WriteByte(byte(t.length))
224 if err != nil {
225 return
229 return nil
232 func marshalBitString(out *forkableWriter, b BitString) (err error) {
233 paddingBits := byte((8 - b.BitLength%8) % 8)
234 err = out.WriteByte(paddingBits)
235 if err != nil {
236 return
238 _, err = out.Write(b.Bytes)
239 return
242 func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
243 if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
244 return StructuralError{"invalid object identifier"}
247 err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
248 if err != nil {
249 return
251 for i := 2; i < len(oid); i++ {
252 err = marshalBase128Int(out, int64(oid[i]))
253 if err != nil {
254 return
258 return
261 func marshalPrintableString(out *forkableWriter, s string) (err error) {
262 b := []byte(s)
263 for _, c := range b {
264 if !isPrintable(c) {
265 return StructuralError{"PrintableString contains invalid character"}
269 _, err = out.Write(b)
270 return
273 func marshalIA5String(out *forkableWriter, s string) (err error) {
274 b := []byte(s)
275 for _, c := range b {
276 if c > 127 {
277 return StructuralError{"IA5String contains invalid character"}
281 _, err = out.Write(b)
282 return
285 func marshalUTF8String(out *forkableWriter, s string) (err error) {
286 _, err = out.Write([]byte(s))
287 return
290 func marshalTwoDigits(out *forkableWriter, v int) (err error) {
291 err = out.WriteByte(byte('0' + (v/10)%10))
292 if err != nil {
293 return
295 return out.WriteByte(byte('0' + v%10))
298 func marshalFourDigits(out *forkableWriter, v int) (err error) {
299 var bytes [4]byte
300 for i := range bytes {
301 bytes[3-i] = '0' + byte(v%10)
302 v /= 10
304 _, err = out.Write(bytes[:])
305 return
308 func outsideUTCRange(t time.Time) bool {
309 year := t.Year()
310 return year < 1950 || year >= 2050
313 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
314 year := t.Year()
316 switch {
317 case 1950 <= year && year < 2000:
318 err = marshalTwoDigits(out, int(year-1900))
319 case 2000 <= year && year < 2050:
320 err = marshalTwoDigits(out, int(year-2000))
321 default:
322 return StructuralError{"cannot represent time as UTCTime"}
324 if err != nil {
325 return
328 return marshalTimeCommon(out, t)
331 func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) {
332 year := t.Year()
333 if year < 0 || year > 9999 {
334 return StructuralError{"cannot represent time as GeneralizedTime"}
336 if err = marshalFourDigits(out, year); err != nil {
337 return
340 return marshalTimeCommon(out, t)
343 func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) {
344 _, month, day := t.Date()
346 err = marshalTwoDigits(out, int(month))
347 if err != nil {
348 return
351 err = marshalTwoDigits(out, day)
352 if err != nil {
353 return
356 hour, min, sec := t.Clock()
358 err = marshalTwoDigits(out, hour)
359 if err != nil {
360 return
363 err = marshalTwoDigits(out, min)
364 if err != nil {
365 return
368 err = marshalTwoDigits(out, sec)
369 if err != nil {
370 return
373 _, offset := t.Zone()
375 switch {
376 case offset/60 == 0:
377 err = out.WriteByte('Z')
378 return
379 case offset > 0:
380 err = out.WriteByte('+')
381 case offset < 0:
382 err = out.WriteByte('-')
385 if err != nil {
386 return
389 offsetMinutes := offset / 60
390 if offsetMinutes < 0 {
391 offsetMinutes = -offsetMinutes
394 err = marshalTwoDigits(out, offsetMinutes/60)
395 if err != nil {
396 return
399 err = marshalTwoDigits(out, offsetMinutes%60)
400 return
403 func stripTagAndLength(in []byte) []byte {
404 _, offset, err := parseTagAndLength(in, 0)
405 if err != nil {
406 return in
408 return in[offset:]
411 func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
412 switch value.Type() {
413 case timeType:
414 t := value.Interface().(time.Time)
415 if outsideUTCRange(t) {
416 return marshalGeneralizedTime(out, t)
417 } else {
418 return marshalUTCTime(out, t)
420 case bitStringType:
421 return marshalBitString(out, value.Interface().(BitString))
422 case objectIdentifierType:
423 return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
424 case bigIntType:
425 return marshalBigInt(out, value.Interface().(*big.Int))
428 switch v := value; v.Kind() {
429 case reflect.Bool:
430 if v.Bool() {
431 return out.WriteByte(255)
432 } else {
433 return out.WriteByte(0)
435 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
436 return marshalInt64(out, int64(v.Int()))
437 case reflect.Struct:
438 t := v.Type()
440 startingField := 0
442 // If the first element of the structure is a non-empty
443 // RawContents, then we don't bother serializing the rest.
444 if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
445 s := v.Field(0)
446 if s.Len() > 0 {
447 bytes := make([]byte, s.Len())
448 for i := 0; i < s.Len(); i++ {
449 bytes[i] = uint8(s.Index(i).Uint())
451 /* The RawContents will contain the tag and
452 * length fields but we'll also be writing
453 * those ourselves, so we strip them out of
454 * bytes */
455 _, err = out.Write(stripTagAndLength(bytes))
456 return
457 } else {
458 startingField = 1
462 for i := startingField; i < t.NumField(); i++ {
463 var pre *forkableWriter
464 pre, out = out.fork()
465 err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
466 if err != nil {
467 return
470 return
471 case reflect.Slice:
472 sliceType := v.Type()
473 if sliceType.Elem().Kind() == reflect.Uint8 {
474 bytes := make([]byte, v.Len())
475 for i := 0; i < v.Len(); i++ {
476 bytes[i] = uint8(v.Index(i).Uint())
478 _, err = out.Write(bytes)
479 return
482 var fp fieldParameters
483 for i := 0; i < v.Len(); i++ {
484 var pre *forkableWriter
485 pre, out = out.fork()
486 err = marshalField(pre, v.Index(i), fp)
487 if err != nil {
488 return
491 return
492 case reflect.String:
493 switch params.stringType {
494 case tagIA5String:
495 return marshalIA5String(out, v.String())
496 case tagPrintableString:
497 return marshalPrintableString(out, v.String())
498 default:
499 return marshalUTF8String(out, v.String())
503 return StructuralError{"unknown Go type"}
506 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
507 // If the field is an interface{} then recurse into it.
508 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
509 return marshalField(out, v.Elem(), params)
512 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
513 return
516 if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
517 return
520 if v.Type() == rawValueType {
521 rv := v.Interface().(RawValue)
522 if len(rv.FullBytes) != 0 {
523 _, err = out.Write(rv.FullBytes)
524 } else {
525 err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
526 if err != nil {
527 return
529 _, err = out.Write(rv.Bytes)
531 return
534 tag, isCompound, ok := getUniversalType(v.Type())
535 if !ok {
536 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
537 return
539 class := classUniversal
541 if params.stringType != 0 && tag != tagPrintableString {
542 return StructuralError{"explicit string type given to non-string member"}
545 switch tag {
546 case tagPrintableString:
547 if params.stringType == 0 {
548 // This is a string without an explicit string type. We'll use
549 // a PrintableString if the character set in the string is
550 // sufficiently limited, otherwise we'll use a UTF8String.
551 for _, r := range v.String() {
552 if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
553 if !utf8.ValidString(v.String()) {
554 return errors.New("asn1: string not valid UTF-8")
556 tag = tagUTF8String
557 break
560 } else {
561 tag = params.stringType
563 case tagUTCTime:
564 if outsideUTCRange(v.Interface().(time.Time)) {
565 tag = tagGeneralizedTime
569 if params.set {
570 if tag != tagSequence {
571 return StructuralError{"non sequence tagged as set"}
573 tag = tagSet
576 tags, body := out.fork()
578 err = marshalBody(body, v, params)
579 if err != nil {
580 return
583 bodyLen := body.Len()
585 var explicitTag *forkableWriter
586 if params.explicit {
587 explicitTag, tags = tags.fork()
590 if !params.explicit && params.tag != nil {
591 // implicit tag.
592 tag = *params.tag
593 class = classContextSpecific
596 err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
597 if err != nil {
598 return
601 if params.explicit {
602 err = marshalTagAndLength(explicitTag, tagAndLength{
603 class: classContextSpecific,
604 tag: *params.tag,
605 length: bodyLen + tags.Len(),
606 isCompound: true,
610 return nil
613 // Marshal returns the ASN.1 encoding of val.
615 // In addition to the struct tags recognised by Unmarshal, the following can be
616 // used:
618 // ia5: causes strings to be marshaled as ASN.1, IA5 strings
619 // omitempty: causes empty slices to be skipped
620 // printable: causes strings to be marshaled as ASN.1, PrintableString strings.
621 // utf8: causes strings to be marshaled as ASN.1, UTF8 strings
622 func Marshal(val interface{}) ([]byte, error) {
623 var out bytes.Buffer
624 v := reflect.ValueOf(val)
625 f := newForkableWriter()
626 err := marshalField(f, v, fieldParameters{})
627 if err != nil {
628 return nil, err
630 _, err = f.writeTo(&out)
631 return out.Bytes(), nil