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