Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / asn1 / marshal.go
blob24548714b211443b26034de6e8ebb2f094e37c54
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 "fmt"
10 "io"
11 "os"
12 "reflect"
13 "time"
16 // A forkableWriter is an in-memory buffer that can be
17 // 'forked' to create new forkableWriters that bracket the
18 // original. After
19 // pre, post := w.fork();
20 // the overall sequence of bytes represented is logically w+pre+post.
21 type forkableWriter struct {
22 *bytes.Buffer
23 pre, post *forkableWriter
26 func newForkableWriter() *forkableWriter {
27 return &forkableWriter{bytes.NewBuffer(nil), nil, nil}
30 func (f *forkableWriter) fork() (pre, post *forkableWriter) {
31 if f.pre != nil || f.post != nil {
32 panic("have already forked")
34 f.pre = newForkableWriter()
35 f.post = newForkableWriter()
36 return f.pre, f.post
39 func (f *forkableWriter) Len() (l int) {
40 l += f.Buffer.Len()
41 if f.pre != nil {
42 l += f.pre.Len()
44 if f.post != nil {
45 l += f.post.Len()
47 return
50 func (f *forkableWriter) writeTo(out io.Writer) (n int, err os.Error) {
51 n, err = out.Write(f.Bytes())
52 if err != nil {
53 return
56 var nn int
58 if f.pre != nil {
59 nn, err = f.pre.writeTo(out)
60 n += nn
61 if err != nil {
62 return
66 if f.post != nil {
67 nn, err = f.post.writeTo(out)
68 n += nn
70 return
73 func marshalBase128Int(out *forkableWriter, n int64) (err os.Error) {
74 if n == 0 {
75 err = out.WriteByte(0)
76 return
79 l := 0
80 for i := n; i > 0; i >>= 7 {
81 l++
84 for i := l - 1; i >= 0; i-- {
85 o := byte(n >> uint(i*7))
86 o &= 0x7f
87 if i != 0 {
88 o |= 0x80
90 err = out.WriteByte(o)
91 if err != nil {
92 return
96 return nil
99 func marshalInt64(out *forkableWriter, i int64) (err os.Error) {
100 n := int64Length(i)
102 for ; n > 0; n-- {
103 err = out.WriteByte(byte(i >> uint((n-1)*8)))
104 if err != nil {
105 return
109 return nil
112 func int64Length(i int64) (numBytes int) {
113 numBytes = 1
115 for i > 127 {
116 numBytes++
117 i >>= 8
120 for i < -128 {
121 numBytes++
122 i >>= 8
125 return
128 func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
129 b := uint8(t.class) << 6
130 if t.isCompound {
131 b |= 0x20
133 if t.tag >= 31 {
134 b |= 0x1f
135 err = out.WriteByte(b)
136 if err != nil {
137 return
139 err = marshalBase128Int(out, int64(t.tag))
140 if err != nil {
141 return
143 } else {
144 b |= uint8(t.tag)
145 err = out.WriteByte(b)
146 if err != nil {
147 return
151 if t.length >= 128 {
152 l := int64Length(int64(t.length))
153 err = out.WriteByte(0x80 | byte(l))
154 if err != nil {
155 return
157 err = marshalInt64(out, int64(t.length))
158 if err != nil {
159 return
161 } else {
162 err = out.WriteByte(byte(t.length))
163 if err != nil {
164 return
168 return nil
171 func marshalBitString(out *forkableWriter, b BitString) (err os.Error) {
172 paddingBits := byte((8 - b.BitLength%8) % 8)
173 err = out.WriteByte(paddingBits)
174 if err != nil {
175 return
177 _, err = out.Write(b.Bytes)
178 return
181 func marshalObjectIdentifier(out *forkableWriter, oid []int) (err os.Error) {
182 if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
183 return StructuralError{"invalid object identifier"}
186 err = out.WriteByte(byte(oid[0]*40 + oid[1]))
187 if err != nil {
188 return
190 for i := 2; i < len(oid); i++ {
191 err = marshalBase128Int(out, int64(oid[i]))
192 if err != nil {
193 return
197 return
200 func marshalPrintableString(out *forkableWriter, s string) (err os.Error) {
201 b := []byte(s)
202 for _, c := range b {
203 if !isPrintable(c) {
204 return StructuralError{"PrintableString contains invalid character"}
208 _, err = out.Write(b)
209 return
212 func marshalIA5String(out *forkableWriter, s string) (err os.Error) {
213 b := []byte(s)
214 for _, c := range b {
215 if c > 127 {
216 return StructuralError{"IA5String contains invalid character"}
220 _, err = out.Write(b)
221 return
224 func marshalTwoDigits(out *forkableWriter, v int) (err os.Error) {
225 err = out.WriteByte(byte('0' + (v/10)%10))
226 if err != nil {
227 return
229 return out.WriteByte(byte('0' + v%10))
232 func marshalUTCTime(out *forkableWriter, t *time.Time) (err os.Error) {
233 switch {
234 case 1950 <= t.Year && t.Year < 2000:
235 err = marshalTwoDigits(out, int(t.Year-1900))
236 case 2000 <= t.Year && t.Year < 2050:
237 err = marshalTwoDigits(out, int(t.Year-2000))
238 default:
239 return StructuralError{"Cannot represent time as UTCTime"}
242 if err != nil {
243 return
246 err = marshalTwoDigits(out, t.Month)
247 if err != nil {
248 return
251 err = marshalTwoDigits(out, t.Day)
252 if err != nil {
253 return
256 err = marshalTwoDigits(out, t.Hour)
257 if err != nil {
258 return
261 err = marshalTwoDigits(out, t.Minute)
262 if err != nil {
263 return
266 err = marshalTwoDigits(out, t.Second)
267 if err != nil {
268 return
271 switch {
272 case t.ZoneOffset/60 == 0:
273 err = out.WriteByte('Z')
274 return
275 case t.ZoneOffset > 0:
276 err = out.WriteByte('+')
277 case t.ZoneOffset < 0:
278 err = out.WriteByte('-')
281 if err != nil {
282 return
285 offsetMinutes := t.ZoneOffset / 60
286 if offsetMinutes < 0 {
287 offsetMinutes = -offsetMinutes
290 err = marshalTwoDigits(out, offsetMinutes/60)
291 if err != nil {
292 return
295 err = marshalTwoDigits(out, offsetMinutes%60)
296 return
299 func stripTagAndLength(in []byte) []byte {
300 _, offset, err := parseTagAndLength(in, 0)
301 if err != nil {
302 return in
304 return in[offset:]
307 func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err os.Error) {
308 switch value.Type() {
309 case timeType:
310 return marshalUTCTime(out, value.Interface().(*time.Time))
311 case bitStringType:
312 return marshalBitString(out, value.Interface().(BitString))
313 case objectIdentifierType:
314 return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
317 switch v := value.(type) {
318 case *reflect.BoolValue:
319 if v.Get() {
320 return out.WriteByte(1)
321 } else {
322 return out.WriteByte(0)
324 case *reflect.IntValue:
325 return marshalInt64(out, int64(v.Get()))
326 case *reflect.StructValue:
327 t := v.Type().(*reflect.StructType)
329 startingField := 0
331 // If the first element of the structure is a non-empty
332 // RawContents, then we don't bother serialising the rest.
333 if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
334 s := v.Field(0).(*reflect.SliceValue)
335 if s.Len() > 0 {
336 bytes := make([]byte, s.Len())
337 for i := 0; i < s.Len(); i++ {
338 bytes[i] = uint8(s.Elem(i).(*reflect.UintValue).Get())
340 /* The RawContents will contain the tag and
341 * length fields but we'll also be writing
342 * those outselves, so we strip them out of
343 * bytes */
344 _, err = out.Write(stripTagAndLength(bytes))
345 return
346 } else {
347 startingField = 1
351 for i := startingField; i < t.NumField(); i++ {
352 var pre *forkableWriter
353 pre, out = out.fork()
354 err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag))
355 if err != nil {
356 return
359 return
360 case *reflect.SliceValue:
361 sliceType := v.Type().(*reflect.SliceType)
362 if sliceType.Elem().Kind() == reflect.Uint8 {
363 bytes := make([]byte, v.Len())
364 for i := 0; i < v.Len(); i++ {
365 bytes[i] = uint8(v.Elem(i).(*reflect.UintValue).Get())
367 _, err = out.Write(bytes)
368 return
371 var params fieldParameters
372 for i := 0; i < v.Len(); i++ {
373 var pre *forkableWriter
374 pre, out = out.fork()
375 err = marshalField(pre, v.Elem(i), params)
376 if err != nil {
377 return
380 return
381 case *reflect.StringValue:
382 if params.stringType == tagIA5String {
383 return marshalIA5String(out, v.Get())
384 } else {
385 return marshalPrintableString(out, v.Get())
387 return
390 return StructuralError{"unknown Go type"}
393 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err os.Error) {
394 // If the field is an interface{} then recurse into it.
395 if v, ok := v.(*reflect.InterfaceValue); ok && v.Type().(*reflect.InterfaceType).NumMethod() == 0 {
396 return marshalField(out, v.Elem(), params)
399 if v.Type() == rawValueType {
400 rv := v.Interface().(RawValue)
401 err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
402 if err != nil {
403 return
405 _, err = out.Write(rv.Bytes)
406 return
409 if params.optional && reflect.DeepEqual(v.Interface(), reflect.MakeZero(v.Type()).Interface()) {
410 return
413 tag, isCompound, ok := getUniversalType(v.Type())
414 if !ok {
415 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
416 return
418 class := classUniversal
420 if params.stringType != 0 {
421 if tag != tagPrintableString {
422 return StructuralError{"Explicit string type given to non-string member"}
424 tag = params.stringType
427 if params.set {
428 if tag != tagSequence {
429 return StructuralError{"Non sequence tagged as set"}
431 tag = tagSet
434 tags, body := out.fork()
436 err = marshalBody(body, v, params)
437 if err != nil {
438 return
441 bodyLen := body.Len()
443 var explicitTag *forkableWriter
444 if params.explicit {
445 explicitTag, tags = tags.fork()
448 if !params.explicit && params.tag != nil {
449 // implicit tag.
450 tag = *params.tag
451 class = classContextSpecific
454 err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
455 if err != nil {
456 return
459 if params.explicit {
460 err = marshalTagAndLength(explicitTag, tagAndLength{
461 class: classContextSpecific,
462 tag: *params.tag,
463 length: bodyLen + tags.Len(),
464 isCompound: true,
468 return nil
471 // Marshal returns the ASN.1 encoding of val.
472 func Marshal(val interface{}) ([]byte, os.Error) {
473 var out bytes.Buffer
474 v := reflect.NewValue(val)
475 f := newForkableWriter()
476 err := marshalField(f, v, fieldParameters{})
477 if err != nil {
478 return nil, err
480 _, err = f.writeTo(&out)
481 return out.Bytes(), nil