github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr/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
    24  and decode XDR data per the data representation standard with the exception
    25  of 128-bit quadruple-precision floating points.  It does not currently implement
    26  parsing of the data specification language.  In other words, the ability to
    27  automatically generate Go code by parsing an XDR data specification file
    28  (typically .x extension) is not supported.  In practice, this limitation of the
    29  package is fairly minor since it is largely unnecessary due to the reflection
    30  capabilities 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 choose
    38  the type of the underlying XDR data based upon the Go type to encode or the target
    39  Go type to decode into.  A description of how each type is mapped is provided
    40  below, however one important type worth reviewing is Go structs.  In the case of
    41  structs, each exported field (first letter capitalized) is reflected and mapped
    42  in order.  As a result, this means a Go struct with exported fields of the
    43  appropriate types listed in the expected order can be used to automatically
    44  encode / decode the XDR data thereby eliminating the need to write a lot of
    45  boilerplate code to encode/decode and error check each piece of XDR data as is
    46  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 arrays
    76      of uint8s require a special struct tag `xdropaque:"false"` since byte
    77      slices and byte arrays are assumed to be opaque data and byte is a Go
    78      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 loops
    82    - Strings are marshalled and unmarshalled with UTF-8 character encoding
    83      which differs from the XDR specification of ASCII, however UTF-8 is
    84      backwards compatible with ASCII so this should rarely cause issues
    85  
    86  # Encoding
    87  
    88  To encode XDR data, use the Marshal function.
    89  
    90  	func Marshal(v interface{}) (rv []byte, err error)
    91  
    92  For example, given the following code snippet:
    93  
    94  	type ImageHeader struct {
    95  		Signature	[3]byte
    96  		Version		uint32
    97  		IsGrayscale	bool
    98  		NumSections	uint32
    99  	}
   100  	h := ImageHeader{[3]byte{0xAB, 0xCD, 0xEF}, 2, true, 10}
   101  
   102  	encodedData, err := xdr.Marshal(&h)
   103  	// Error check elided
   104  
   105  The result, encodedData, will then contain the following XDR encoded byte
   106  sequence:
   107  
   108  	0xAB, 0xCD, 0xEF, 0x00,
   109  	0x00, 0x00, 0x00, 0x02,
   110  	0x00, 0x00, 0x00, 0x01,
   111  	0x00, 0x00, 0x00, 0x0A
   112  
   113  In addition, while the automatic marshalling discussed above will work for the
   114  vast majority of cases, an Encoder object is provided that can be used to
   115  manually encode XDR primitives for complex scenarios where automatic
   116  reflection-based encoding won't work.  The included examples provide a sample of
   117  manual usage via an Encoder.
   118  
   119  # Decoding
   120  
   121  To decode XDR data, use the Unmarshal function.
   122  
   123  	func Unmarshal(data []byte, v interface{}) (rest []byte, err error)
   124  
   125  For example, given the following code snippet:
   126  
   127  	type ImageHeader struct {
   128  		Signature	[3]byte
   129  		Version		uint32
   130  		IsGrayscale	bool
   131  		NumSections	uint32
   132  	}
   133  
   134  	// Using output from the Encoding section above.
   135  	encodedData := []byte{
   136  		0xAB, 0xCD, 0xEF, 0x00,
   137  		0x00, 0x00, 0x00, 0x02,
   138  		0x00, 0x00, 0x00, 0x01,
   139  		0x00, 0x00, 0x00, 0x0A}
   140  
   141  	var h ImageHeader
   142  	remainingBytes, err := xdr.Unmarshal(encodedData, &h)
   143  	// Error check elided
   144  
   145  The struct instance, h, will then contain the following values:
   146  
   147  	h.Signature = [3]byte{0xAB, 0xCD, 0xEF}
   148  	h.Version = 2
   149  	h.IsGrayscale = true
   150  	h.NumSections = 10
   151  
   152  In addition, while the automatic unmarshalling discussed above will work for the
   153  vast majority of cases, a Decoder object is provided that can be used to
   154  manually decode XDR primitives for complex scenarios where automatic
   155  reflection-based decoding won't work.  The included examples provide a sample of
   156  manual usage via an Decoder.
   157  
   158  # Errors
   159  
   160  All errors are either of type UnmarshalError or MarshalError.  Both provide
   161  human readable output as well as an ErrorCode field which can be inspected by
   162  sophisticated callers if necessary
   163  
   164  See the documentation of UnmarshalError, MarshalError, and ErrorCode for further
   165  details.
   166  */
   167  package xdr