podman

Форк
0
669 строк · 20.7 Кб
1
/*
2
 * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
 */
16

17
package xdr
18

19
import (
20
	"fmt"
21
	"io"
22
	"math"
23
	"reflect"
24
	"time"
25
)
26

27
var errIOEncode = "%s while encoding %d bytes"
28

29
/*
30
Marshal writes the XDR encoding of v to writer w and returns the number of bytes
31
written.  It traverses v recursively and automatically indirects pointers
32
through arbitrary depth to encode the actual value pointed to.
33

34
Marshal uses reflection to determine the type of the concrete value contained by
35
v and performs a mapping of Go types to the underlying XDR types as follows:
36

37
	Go Type -> XDR Type
38
	--------------------
39
	int8, int16, int32, int -> XDR Integer
40
	uint8, uint16, uint32, uint -> XDR Unsigned Integer
41
	int64 -> XDR Hyper Integer
42
	uint64 -> XDR Unsigned Hyper Integer
43
	bool -> XDR Boolean
44
	float32 -> XDR Floating-Point
45
	float64 -> XDR Double-Precision Floating-Point
46
	string -> XDR String
47
	byte -> XDR Integer
48
	[]byte -> XDR Variable-Length Opaque Data
49
	[#]byte -> XDR Fixed-Length Opaque Data
50
	[]<type> -> XDR Variable-Length Array
51
	[#]<type> -> XDR Fixed-Length Array
52
	struct -> XDR Structure
53
	map -> XDR Variable-Length Array of two-element XDR Structures
54
	time.Time -> XDR String encoded with RFC3339 nanosecond precision
55

56
Notes and Limitations:
57

58
	* Automatic marshalling of variable and fixed-length arrays of uint8s
59
	  requires a special struct tag `xdropaque:"false"` since byte slices and
60
	  byte arrays are assumed to be opaque data and byte is a Go alias for uint8
61
	  thus indistinguishable under reflection
62
	* Channel, complex, and function types cannot be encoded
63
	* Interfaces without a concrete value cannot be encoded
64
	* Cyclic data structures are not supported and will result in infinite loops
65
	* Strings are marshalled with UTF-8 character encoding which differs from
66
	  the XDR specification of ASCII, however UTF-8 is backwards compatible with
67
	  ASCII so this should rarely cause issues
68

69
If any issues are encountered during the marshalling process, a MarshalError is
70
returned with a human readable description as well as an ErrorCode value for
71
further inspection from sophisticated callers.  Some potential issues are
72
unsupported Go types, attempting to encode more opaque data than can be
73
represented by a single opaque XDR entry, and exceeding max slice limitations.
74
*/
75
func Marshal(w io.Writer, v interface{}) (int, error) {
76
	enc := Encoder{w: w}
77
	return enc.Encode(v)
78
}
79

80
// An Encoder wraps an io.Writer that will receive the XDR encoded byte stream.
81
// See NewEncoder.
82
type Encoder struct {
83
	w io.Writer
84
}
85

86
// EncodeInt writes the XDR encoded representation of the passed 32-bit signed
87
// integer to the encapsulated writer and returns the number of bytes written.
88
//
89
// A MarshalError with an error code of ErrIO is returned if writing the data
90
// fails.
91
//
92
// Reference:
93
// 	RFC Section 4.1 - Integer
94
// 	32-bit big-endian signed integer in range [-2147483648, 2147483647]
95
func (enc *Encoder) EncodeInt(v int32) (int, error) {
96
	var b [4]byte
97
	b[0] = byte(v >> 24)
98
	b[1] = byte(v >> 16)
99
	b[2] = byte(v >> 8)
100
	b[3] = byte(v)
101

102
	n, err := enc.w.Write(b[:])
103
	if err != nil {
104
		msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
105
		err := marshalError("EncodeInt", ErrIO, msg, b[:n], err)
106
		return n, err
107
	}
108

109
	return n, nil
110
}
111

112
// EncodeUint writes the XDR encoded representation of the passed 32-bit
113
// unsigned integer to the encapsulated writer and returns the number of bytes
114
// written.
115
//
116
// A MarshalError with an error code of ErrIO is returned if writing the data
117
// fails.
118
//
119
// Reference:
120
// 	RFC Section 4.2 - Unsigned Integer
121
// 	32-bit big-endian unsigned integer in range [0, 4294967295]
122
func (enc *Encoder) EncodeUint(v uint32) (int, error) {
123
	var b [4]byte
124
	b[0] = byte(v >> 24)
125
	b[1] = byte(v >> 16)
126
	b[2] = byte(v >> 8)
127
	b[3] = byte(v)
128

129
	n, err := enc.w.Write(b[:])
130
	if err != nil {
131
		msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
132
		err := marshalError("EncodeUint", ErrIO, msg, b[:n], err)
133
		return n, err
134
	}
135

136
	return n, nil
137
}
138

139
// EncodeEnum treats the passed 32-bit signed integer as an enumeration value
140
// and, if it is in the list of passed valid enumeration values, writes the XDR
141
// encoded representation of it to the encapsulated writer.  It returns the
142
// number of bytes written.
143
//
144
// A MarshalError is returned if the enumeration value is not one of the
145
// provided valid values or if writing the data fails.
146
//
147
// Reference:
148
// 	RFC Section 4.3 - Enumeration
149
// 	Represented as an XDR encoded signed integer
150
func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (int, error) {
151
	if !validEnums[v] {
152
		err := marshalError("EncodeEnum", ErrBadEnumValue,
153
			"invalid enum", v, nil)
154
		return 0, err
155
	}
156
	return enc.EncodeInt(v)
157
}
158

159
// EncodeBool writes the XDR encoded representation of the passed boolean to the
160
// encapsulated writer and returns the number of bytes written.
161
//
162
// A MarshalError with an error code of ErrIO is returned if writing the data
163
// fails.
164
//
165
// Reference:
166
// 	RFC Section 4.4 - Boolean
167
// 	Represented as an XDR encoded enumeration where 0 is false and 1 is true
168
func (enc *Encoder) EncodeBool(v bool) (int, error) {
169
	i := int32(0)
170
	if v == true {
171
		i = 1
172
	}
173
	return enc.EncodeInt(i)
174
}
175

176
// EncodeHyper writes the XDR encoded representation of the passed 64-bit
177
// signed integer to the encapsulated writer and returns the number of bytes
178
// written.
179
//
180
// A MarshalError with an error code of ErrIO is returned if writing the data
181
// fails.
182
//
183
// Reference:
184
// 	RFC Section 4.5 - Hyper Integer
185
// 	64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
186
func (enc *Encoder) EncodeHyper(v int64) (int, error) {
187
	var b [8]byte
188
	b[0] = byte(v >> 56)
189
	b[1] = byte(v >> 48)
190
	b[2] = byte(v >> 40)
191
	b[3] = byte(v >> 32)
192
	b[4] = byte(v >> 24)
193
	b[5] = byte(v >> 16)
194
	b[6] = byte(v >> 8)
195
	b[7] = byte(v)
196

197
	n, err := enc.w.Write(b[:])
198
	if err != nil {
199
		msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
200
		err := marshalError("EncodeHyper", ErrIO, msg, b[:n], err)
201
		return n, err
202
	}
203

204
	return n, nil
205
}
206

207
// EncodeUhyper writes the XDR encoded representation of the passed 64-bit
208
// unsigned integer to the encapsulated writer and returns the number of bytes
209
// written.
210
//
211
// A MarshalError with an error code of ErrIO is returned if writing the data
212
// fails.
213
//
214
// Reference:
215
// 	RFC Section 4.5 - Unsigned Hyper Integer
216
// 	64-bit big-endian unsigned integer in range [0, 18446744073709551615]
217
func (enc *Encoder) EncodeUhyper(v uint64) (int, error) {
218
	var b [8]byte
219
	b[0] = byte(v >> 56)
220
	b[1] = byte(v >> 48)
221
	b[2] = byte(v >> 40)
222
	b[3] = byte(v >> 32)
223
	b[4] = byte(v >> 24)
224
	b[5] = byte(v >> 16)
225
	b[6] = byte(v >> 8)
226
	b[7] = byte(v)
227

228
	n, err := enc.w.Write(b[:])
229
	if err != nil {
230
		msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
231
		err := marshalError("EncodeUhyper", ErrIO, msg, b[:n], err)
232
		return n, err
233
	}
234

235
	return n, nil
236
}
237

238
// EncodeFloat writes the XDR encoded representation of the passed 32-bit
239
// (single-precision) floating point to the encapsulated writer and returns the
240
// number of bytes written.
241
//
242
// A MarshalError with an error code of ErrIO is returned if writing the data
243
// fails.
244
//
245
// Reference:
246
// 	RFC Section 4.6 - Floating Point
247
// 	32-bit single-precision IEEE 754 floating point
248
func (enc *Encoder) EncodeFloat(v float32) (int, error) {
249
	ui := math.Float32bits(v)
250
	return enc.EncodeUint(ui)
251
}
252

253
// EncodeDouble writes the XDR encoded representation of the passed 64-bit
254
// (double-precision) floating point to the encapsulated writer and returns the
255
// number of bytes written.
256
//
257
// A MarshalError with an error code of ErrIO is returned if writing the data
258
// fails.
259
//
260
// Reference:
261
// 	RFC Section 4.7 -  Double-Precision Floating Point
262
// 	64-bit double-precision IEEE 754 floating point
263
func (enc *Encoder) EncodeDouble(v float64) (int, error) {
264
	ui := math.Float64bits(v)
265
	return enc.EncodeUhyper(ui)
266
}
267

268
// RFC Section 4.8 -  Quadruple-Precision Floating Point
269
// 128-bit quadruple-precision floating point
270
// Not Implemented
271

272
// EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
273
// size and writes the XDR encoded representation of it  to the encapsulated
274
// writer.  It returns the number of bytes written.
275
//
276
// A MarshalError with an error code of ErrIO is returned if writing the data
277
// fails.
278
//
279
// Reference:
280
// 	RFC Section 4.9 - Fixed-Length Opaque Data
281
// 	Fixed-length uninterpreted data zero-padded to a multiple of four
282
func (enc *Encoder) EncodeFixedOpaque(v []byte) (int, error) {
283
	l := len(v)
284
	pad := (4 - (l % 4)) % 4
285

286
	// Write the actual bytes.
287
	n, err := enc.w.Write(v)
288
	if err != nil {
289
		msg := fmt.Sprintf(errIOEncode, err.Error(), len(v))
290
		err := marshalError("EncodeFixedOpaque", ErrIO, msg, v[:n], err)
291
		return n, err
292
	}
293

294
	// Write any padding if needed.
295
	if pad > 0 {
296
		b := make([]byte, pad)
297
		n2, err := enc.w.Write(b)
298
		n += n2
299
		if err != nil {
300
			written := make([]byte, l+n2)
301
			copy(written, v)
302
			copy(written[l:], b[:n2])
303
			msg := fmt.Sprintf(errIOEncode, err.Error(), l+pad)
304
			err := marshalError("EncodeFixedOpaque", ErrIO, msg,
305
				written, err)
306
			return n, err
307
		}
308
	}
309

310
	return n, nil
311
}
312

313
// EncodeOpaque treats the passed byte slice as opaque data of a variable
314
// size and writes the XDR encoded representation of it to the encapsulated
315
// writer.  It returns the number of bytes written.
316
//
317
// A MarshalError with an error code of ErrIO is returned if writing the data
318
// fails.
319
//
320
// Reference:
321
// 	RFC Section 4.10 - Variable-Length Opaque Data
322
// 	Unsigned integer length followed by fixed opaque data of that length
323
func (enc *Encoder) EncodeOpaque(v []byte) (int, error) {
324
	// Length of opaque data.
325
	n, err := enc.EncodeUint(uint32(len(v)))
326
	if err != nil {
327
		return n, err
328
	}
329

330
	n2, err := enc.EncodeFixedOpaque(v)
331
	n += n2
332
	return n, err
333
}
334

335
// EncodeString writes the XDR encoded representation of the passed string
336
// to the encapsulated writer and returns the number of bytes written.
337
// Character encoding is assumed to be UTF-8 and therefore ASCII compatible.  If
338
// the underlying character encoding is not compatible with this assumption, the
339
// data can instead be written as variable-length opaque data (EncodeOpaque) and
340
// manually converted as needed.
341
//
342
// A MarshalError with an error code of ErrIO is returned if writing the data
343
// fails.
344
//
345
// Reference:
346
// 	RFC Section 4.11 - String
347
// 	Unsigned integer length followed by bytes zero-padded to a multiple of four
348
func (enc *Encoder) EncodeString(v string) (int, error) {
349
	// Length of string.
350
	n, err := enc.EncodeUint(uint32(len(v)))
351
	if err != nil {
352
		return n, err
353
	}
354

355
	n2, err := enc.EncodeFixedOpaque([]byte(v))
356
	n += n2
357
	return n, err
358
}
359

360
// encodeFixedArray writes the XDR encoded representation of each element
361
// in the passed array represented by the reflection value to the encapsulated
362
// writer and returns the number of bytes written.  The ignoreOpaque flag
363
// controls whether or not uint8 (byte) elements should be encoded individually
364
// or as a fixed sequence of opaque data.
365
//
366
// A MarshalError is returned if any issues are encountered while encoding
367
// the array elements.
368
//
369
// Reference:
370
// 	RFC Section 4.12 - Fixed-Length Array
371
// 	Individually XDR encoded array elements
372
func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
373
	// Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
374
	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
375
		// Create a slice of the underlying array for better efficiency
376
		// when possible.  Can't create a slice of an unaddressable
377
		// value.
378
		if v.CanAddr() {
379
			return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
380
		}
381

382
		// When the underlying array isn't addressable fall back to
383
		// copying the array into a new slice.  This is rather ugly, but
384
		// the inability to create a constant slice from an
385
		// unaddressable array is a limitation of Go.
386
		slice := make([]byte, v.Len(), v.Len())
387
		reflect.Copy(reflect.ValueOf(slice), v)
388
		return enc.EncodeFixedOpaque(slice)
389
	}
390

391
	// Encode each array element.
392
	var n int
393
	for i := 0; i < v.Len(); i++ {
394
		n2, err := enc.encode(v.Index(i))
395
		n += n2
396
		if err != nil {
397
			return n, err
398
		}
399
	}
400

401
	return n, nil
402
}
403

404
// encodeArray writes an XDR encoded integer representing the number of
405
// elements in the passed slice represented by the reflection value followed by
406
// the XDR encoded representation of each element in slice to the encapsulated
407
// writer and returns the number of bytes written.  The ignoreOpaque flag
408
// controls whether or not uint8 (byte) elements should be encoded individually
409
// or as a variable sequence of opaque data.
410
//
411
// A MarshalError is returned if any issues are encountered while encoding
412
// the array elements.
413
//
414
// Reference:
415
// 	RFC Section 4.13 - Variable-Length Array
416
// 	Unsigned integer length followed by individually XDR encoded array elements
417
func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
418
	numItems := uint32(v.Len())
419
	n, err := enc.EncodeUint(numItems)
420
	if err != nil {
421
		return n, err
422
	}
423

424
	n2, err := enc.encodeFixedArray(v, ignoreOpaque)
425
	n += n2
426
	return n, err
427
}
428

429
// encodeStruct writes an XDR encoded representation of each value in the
430
// exported fields of the struct represented by the passed reflection value to
431
// the encapsulated writer and returns the number of bytes written.  Pointers
432
// are automatically indirected through arbitrary depth to encode the actual
433
// value pointed to.
434
//
435
// A MarshalError is returned if any issues are encountered while encoding
436
// the elements.
437
//
438
// Reference:
439
// 	RFC Section 4.14 - Structure
440
// 	XDR encoded elements in the order of their declaration in the struct
441
func (enc *Encoder) encodeStruct(v reflect.Value) (int, error) {
442
	var n int
443
	vt := v.Type()
444
	for i := 0; i < v.NumField(); i++ {
445
		// Skip unexported fields and indirect through pointers.
446
		vtf := vt.Field(i)
447
		if vtf.PkgPath != "" {
448
			continue
449
		}
450
		vf := v.Field(i)
451
		vf = enc.indirect(vf)
452

453
		// Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
454
		tag := vtf.Tag.Get("xdropaque")
455
		if tag == "false" {
456
			switch vf.Kind() {
457
			case reflect.Slice:
458
				n2, err := enc.encodeArray(vf, true)
459
				n += n2
460
				if err != nil {
461
					return n, err
462
				}
463
				continue
464

465
			case reflect.Array:
466
				n2, err := enc.encodeFixedArray(vf, true)
467
				n += n2
468
				if err != nil {
469
					return n, err
470
				}
471
				continue
472
			}
473
		}
474

475
		// Encode each struct field.
476
		n2, err := enc.encode(vf)
477
		n += n2
478
		if err != nil {
479
			return n, err
480
		}
481
	}
482

483
	return n, nil
484
}
485

486
// RFC Section 4.15 - Discriminated Union
487
// RFC Section 4.16 - Void
488
// RFC Section 4.17 - Constant
489
// RFC Section 4.18 - Typedef
490
// RFC Section 4.19 - Optional data
491
// RFC Sections 4.15 though 4.19 only apply to the data specification language
492
// which is not implemented by this package.  In the case of discriminated
493
// unions, struct tags are used to perform a similar function.
494

495
// encodeMap treats the map represented by the passed reflection value as a
496
// variable-length array of 2-element structures whose fields are of the same
497
// type as the map keys and elements and writes its XDR encoded representation
498
// to the encapsulated writer.  It returns the number of bytes written.
499
//
500
// A MarshalError is returned if any issues are encountered while encoding
501
// the elements.
502
func (enc *Encoder) encodeMap(v reflect.Value) (int, error) {
503
	// Number of elements.
504
	n, err := enc.EncodeUint(uint32(v.Len()))
505
	if err != nil {
506
		return n, err
507
	}
508

509
	// Encode each key and value according to their type.
510
	for _, key := range v.MapKeys() {
511
		n2, err := enc.encode(key)
512
		n += n2
513
		if err != nil {
514
			return n, err
515
		}
516

517
		n2, err = enc.encode(v.MapIndex(key))
518
		n += n2
519
		if err != nil {
520
			return n, err
521
		}
522
	}
523

524
	return n, nil
525
}
526

527
// encodeInterface examines the interface represented by the passed reflection
528
// value to detect whether it is an interface that can be encoded if it is,
529
// extracts the underlying value to pass back into the encode function for
530
// encoding according to its type.
531
//
532
// A MarshalError is returned if any issues are encountered while encoding
533
// the interface.
534
func (enc *Encoder) encodeInterface(v reflect.Value) (int, error) {
535
	if v.IsNil() || !v.CanInterface() {
536
		msg := fmt.Sprintf("can't encode nil interface")
537
		err := marshalError("encodeInterface", ErrNilInterface, msg,
538
			nil, nil)
539
		return 0, err
540
	}
541

542
	// Extract underlying value from the interface and indirect through pointers.
543
	ve := reflect.ValueOf(v.Interface())
544
	ve = enc.indirect(ve)
545
	return enc.encode(ve)
546
}
547

548
// encode is the main workhorse for marshalling via reflection.  It uses
549
// the passed reflection value to choose the XDR primitives to encode into
550
// the encapsulated writer and returns the number of bytes written.  It is a
551
// recursive function, so cyclic data structures are not supported and will
552
// result in an infinite loop.
553
func (enc *Encoder) encode(v reflect.Value) (int, error) {
554
	if !v.IsValid() {
555
		msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
556
		err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
557
		return 0, err
558
	}
559

560
	// Indirect through pointers to get at the concrete value.
561
	ve := enc.indirect(v)
562

563
	// Handle time.Time values by encoding them as an RFC3339 formatted
564
	// string with nanosecond precision.  Check the type string before
565
	// doing a full blown conversion to interface and type assertion since
566
	// checking a string is much quicker.
567
	if ve.Type().String() == "time.Time" && ve.CanInterface() {
568
		viface := ve.Interface()
569
		if tv, ok := viface.(time.Time); ok {
570
			return enc.EncodeString(tv.Format(time.RFC3339Nano))
571
		}
572
	}
573

574
	// Handle native Go types.
575
	switch ve.Kind() {
576
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
577
		return enc.EncodeInt(int32(ve.Int()))
578

579
	case reflect.Int64:
580
		return enc.EncodeHyper(ve.Int())
581

582
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
583
		return enc.EncodeUint(uint32(ve.Uint()))
584

585
	case reflect.Uint64:
586
		return enc.EncodeUhyper(ve.Uint())
587

588
	case reflect.Bool:
589
		return enc.EncodeBool(ve.Bool())
590

591
	case reflect.Float32:
592
		return enc.EncodeFloat(float32(ve.Float()))
593

594
	case reflect.Float64:
595
		return enc.EncodeDouble(ve.Float())
596

597
	case reflect.String:
598
		return enc.EncodeString(ve.String())
599

600
	case reflect.Array:
601
		return enc.encodeFixedArray(ve, false)
602

603
	case reflect.Slice:
604
		return enc.encodeArray(ve, false)
605

606
	case reflect.Struct:
607
		return enc.encodeStruct(ve)
608

609
	case reflect.Map:
610
		return enc.encodeMap(ve)
611

612
	case reflect.Interface:
613
		return enc.encodeInterface(ve)
614
	}
615

616
	// The only unhandled types left are unsupported.  At the time of this
617
	// writing the only remaining unsupported types that exist are
618
	// reflect.Uintptr and reflect.UnsafePointer.
619
	msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
620
	err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
621
	return 0, err
622
}
623

624
// indirect dereferences pointers until it reaches a non-pointer.  This allows
625
// transparent encoding through arbitrary levels of indirection.
626
func (enc *Encoder) indirect(v reflect.Value) reflect.Value {
627
	rv := v
628
	for rv.Kind() == reflect.Ptr {
629
		rv = rv.Elem()
630
	}
631
	return rv
632
}
633

634
// Encode operates identically to the Marshal function with the exception of
635
// using the writer associated with the Encoder for the destination of the
636
// XDR-encoded data instead of a user-supplied writer.  See the Marshal
637
// documentation for specifics.
638
func (enc *Encoder) Encode(v interface{}) (int, error) {
639
	if v == nil {
640
		msg := "can't marshal nil interface"
641
		err := marshalError("Marshal", ErrNilInterface, msg, nil, nil)
642
		return 0, err
643
	}
644

645
	vv := reflect.ValueOf(v)
646
	vve := vv
647
	for vve.Kind() == reflect.Ptr {
648
		if vve.IsNil() {
649
			msg := fmt.Sprintf("can't marshal nil pointer '%v'",
650
				vv.Type().String())
651
			err := marshalError("Marshal", ErrBadArguments, msg,
652
				nil, nil)
653
			return 0, err
654
		}
655
		vve = vve.Elem()
656
	}
657

658
	return enc.encode(vve)
659
}
660

661
// NewEncoder returns an object that can be used to manually choose fields to
662
// XDR encode to the passed writer w.  Typically, Marshal should be used instead
663
// of manually creating an Encoder. An Encoder, along with several of its
664
// methods to encode XDR primitives, is exposed so it is possible to perform
665
// manual encoding of data without relying on reflection should it be necessary
666
// in complex scenarios where automatic reflection-based encoding won't work.
667
func NewEncoder(w io.Writer) *Encoder {
668
	return &Encoder{w: w}
669
}
670

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.