github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr3/doc.go (about) 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 /* 18 Package xdr implements the data representation portion of the External Data 19 Representation (XDR) standard protocol as specified in RFC 4506 (obsoletes 20 RFC 1832 and RFC 1014). 21 22 The XDR RFC defines both a data specification language and a data 23 representation standard. This package implements methods to encode and decode 24 XDR data per the data representation standard with the exception of 128-bit 25 quadruple-precision floating points. It does not currently implement parsing of 26 the data specification language. In other words, the ability to automatically 27 generate Go code by parsing an XDR data specification file (typically .x 28 extension) is not supported. In practice, this limitation of the package is 29 fairly minor since it is largely unnecessary due to the reflection capabilities 30 of Go as described below. 31 32 This package provides two approaches for encoding and decoding XDR data: 33 34 1. Marshal/Unmarshal functions which automatically map between XDR and Go types 35 2. Individual Encoder/Decoder objects to manually work with XDR primitives 36 37 For the Marshal/Unmarshal functions, Go reflection capabilities are used to 38 choose the type of the underlying XDR data based upon the Go type to encode or 39 the target Go type to decode into. A description of how each type is mapped is 40 provided below, however one important type worth reviewing is Go structs. In 41 the case of structs, each exported field (first letter capitalized) is reflected 42 and mapped in order. As a result, this means a Go struct with exported fields 43 of the appropriate types listed in the expected order can be used to 44 automatically encode / decode the XDR data thereby eliminating the need to write 45 a lot of boilerplate code to encode/decode and error check each piece of XDR 46 data as is typically required with C based XDR libraries. 47 48 # Go Type to XDR Type Mappings 49 50 The following chart shows an overview of how Go types are mapped to XDR types 51 for automatic marshalling and unmarshalling. The documentation for the Marshal 52 and Unmarshal functions has specific details of how the mapping proceeds. 53 54 Go Type <-> XDR Type 55 -------------------- 56 int8, int16, int32, int <-> XDR Integer 57 uint8, uint16, uint32, uint <-> XDR Unsigned Integer 58 int64 <-> XDR Hyper Integer 59 uint64 <-> XDR Unsigned Hyper Integer 60 bool <-> XDR Boolean 61 float32 <-> XDR Floating-Point 62 float64 <-> XDR Double-Precision Floating-Point 63 string <-> XDR String 64 byte <-> XDR Integer 65 []byte <-> XDR Variable-Length Opaque Data 66 [#]byte <-> XDR Fixed-Length Opaque Data 67 []<type> <-> XDR Variable-Length Array 68 [#]<type> <-> XDR Fixed-Length Array 69 struct <-> XDR Structure 70 map <-> XDR Variable-Length Array of two-element XDR Structures 71 time.Time <-> XDR String encoded with RFC3339 nanosecond precision 72 73 Notes and Limitations: 74 75 - Automatic marshalling and unmarshalling of variable and fixed-length 76 arrays of uint8s require a special struct tag `xdropaque:"false"` 77 since byte slices and byte arrays are assumed to be opaque data and 78 byte is a Go alias for uint8 thus indistinguishable under reflection 79 - Channel, complex, and function types cannot be encoded 80 - Interfaces without a concrete value cannot be encoded 81 - Cyclic data structures are not supported and will result in infinite 82 loops 83 - Strings are marshalled and unmarshalled with UTF-8 character encoding 84 which differs from the XDR specification of ASCII, however UTF-8 is 85 backwards compatible with ASCII so this should rarely cause issues 86 87 # Encoding 88 89 To encode XDR data, use the Marshal function. 90 91 func Marshal(w io.Writer, v interface{}) (int, error) 92 93 For example, given the following code snippet: 94 95 type ImageHeader struct { 96 Signature [3]byte 97 Version uint32 98 IsGrayscale bool 99 NumSections uint32 100 } 101 h := ImageHeader{[3]byte{0xAB, 0xCD, 0xEF}, 2, true, 10} 102 103 var w bytes.Buffer 104 bytesWritten, err := xdr.Marshal(&w, &h) 105 // Error check elided 106 107 The result, encodedData, will then contain the following XDR encoded byte 108 sequence: 109 110 0xAB, 0xCD, 0xEF, 0x00, 111 0x00, 0x00, 0x00, 0x02, 112 0x00, 0x00, 0x00, 0x01, 113 0x00, 0x00, 0x00, 0x0A 114 115 In addition, while the automatic marshalling discussed above will work for the 116 vast majority of cases, an Encoder object is provided that can be used to 117 manually encode XDR primitives for complex scenarios where automatic 118 reflection-based encoding won't work. The included examples provide a sample of 119 manual usage via an Encoder. 120 121 # Decoding 122 123 To decode XDR data, use the Unmarshal function. 124 125 func Unmarshal(r io.Reader, v interface{}) (int, error) 126 127 For example, given the following code snippet: 128 129 type ImageHeader struct { 130 Signature [3]byte 131 Version uint32 132 IsGrayscale bool 133 NumSections uint32 134 } 135 136 // Using output from the Encoding section above. 137 encodedData := []byte{ 138 0xAB, 0xCD, 0xEF, 0x00, 139 0x00, 0x00, 0x00, 0x02, 140 0x00, 0x00, 0x00, 0x01, 141 0x00, 0x00, 0x00, 0x0A, 142 } 143 144 var h ImageHeader 145 bytesRead, err := xdr.Unmarshal(bytes.NewReader(encodedData), &h) 146 // Error check elided 147 148 The struct instance, h, will then contain the following values: 149 150 h.Signature = [3]byte{0xAB, 0xCD, 0xEF} 151 h.Version = 2 152 h.IsGrayscale = true 153 h.NumSections = 10 154 155 In addition, while the automatic unmarshalling discussed above will work for the 156 vast majority of cases, a Decoder object is provided that can be used to 157 manually decode XDR primitives for complex scenarios where automatic 158 reflection-based decoding won't work. The included examples provide a sample of 159 manual usage via a Decoder. 160 161 # Errors 162 163 All errors are either of type UnmarshalError or MarshalError. Both provide 164 human-readable output as well as an ErrorCode field which can be inspected by 165 sophisticated callers if necessary. 166 167 See the documentation of UnmarshalError, MarshalError, and ErrorCode for further 168 details. 169 */ 170 package xdr