github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/doc.go (about)

     1  // Copyright 2020 DataStax
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package datacodec contains functionality to encode and decode CQL data.
    16  //
    17  // This package is not used anywhere in this library, but can be used by client code to encode and decode actual CQL
    18  // values sent to or received from any Cassandra-compatible backend.
    19  //
    20  // `datacodec.Codec` is its main interface, and it has two main methods:
    21  //
    22  //  // Encode encodes the given source into dest. The parameter source must be a value of a supported Go type for the
    23  //  // CQL type being encoded, or a pointer thereto; a nil value is encoded as a CQL NULL.
    24  //  Encode(source interface{}, version primitive.ProtocolVersion) (dest []byte, err error)
    25  //
    26  //  // Decode decodes the given source into dest. The parameter dest must be a pointer to a supported Go type for
    27  //  // the CQL type being decoded; it cannot be nil. If return parameter wasNull is true, then the decoded value was a
    28  //  // NULL, in which case the actual value stored in dest will be set to its zero value.
    29  //  Decode(source []byte, dest interface{}, version primitive.ProtocolVersion) (wasNull bool, err error)
    30  //
    31  // Obtaining a codec
    32  //
    33  // It is not required to implement the datacodec.Codec interface unless a custom encoding/decoding scheme must be used.
    34  // The NewCodec function can be used to obtain a codec for a all valid CQL types, including complex ones (lists, sets,
    35  // maps, tuples and user-defined types).
    36  //
    37  // Simple CQL types also have a global codec available; for example the datacodec.Varchar codec can be used to decode
    38  // and encode to CQL varchar.
    39  //
    40  // Codecs for complex types can be obtained through constructor functions:
    41  //
    42  //  - NewList
    43  //  - NewSet
    44  //  - NewMap
    45  //  - NewTuple
    46  //  - NewUserDefined
    47  //
    48  // Using a codec
    49  //
    50  // Codecs accept a wide variety of inputs, but they have a "preferred" Go type that is the ideal representation of the
    51  // CQL type in Go. In the table below, preferred types are listed first.
    52  //
    53  //  CQL type              | Accepted Go types (1)                           | Notes
    54  //  bigint, counter       | int64, *int64                                   |
    55  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  |
    56  //                        | *big.Int                                        |
    57  //                        | string, *string                                 | formatted and parsed as base 10 number
    58  //  blob                  | []byte, *[]byte                                 |
    59  //                        | string, *string                                 |
    60  //  boolean               | bool, *bool                                     |
    61  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  | zero=false, other=true
    62  //  date                  | time.Time, *time.Time                           | time at start of day (in UTC); clock part set to zero
    63  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  | days since Unix epoch
    64  //                        | string, *string                                 | parsed according to layout, default is "2006-01-02"
    65  //  decimal               | CqlDecimal, *CqlDecimal                         |
    66  //  double                | float64, *float64                               |
    67  //                        | float32, *float32                               |
    68  //                        | *big.Float                                      |
    69  //  duration              | CqlDuration, *CqlDuration                       |
    70  //  float                 | float32, *float32                               |
    71  //                        | float64, *float64                               |
    72  //  inet                  | net.IP, *net.IP                                 |
    73  //                        | []byte, *[]byte                                 |
    74  //                        | string, *string                                 | parsed with net.ParseIP
    75  //  int                   | int32, *int32                                   |
    76  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  |
    77  //                        | string, *string                                 | formatted and parsed as base 10 number
    78  //  list, set             | any compatible slice                            | element types must match
    79  //                        | any compatible array                            | element types must match
    80  //  map                   | any compatible map                              | key and value types must match
    81  //  smallint              | int16, *int16                                   |
    82  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  |
    83  //                        | string, *string                                 | formatted and parsed as base 10 number
    84  //  time                  | time.Duration, *time.Duration                   |
    85  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  | nanoseconds since start of day
    86  //                        | time.Time, *time.Time                           | time since start of day (in UTC); date part set to zero
    87  //                        | string, *string                                 | parsed according to layout, default is "15:04:05.999999999"
    88  //  timestamp             | time.Time, *time.Time                           |
    89  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  | milliseconds since Unix epoch
    90  //                        | string, *string                                 | parsed according to layout and location, defaults are "2006-01-02T15:04:05.999999999-07:00" and UTC
    91  //  tinyint               | int8, *int8                                     |
    92  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  |
    93  //                        | string, *string                                 | formatted and parsed as base 10 number
    94  //  tuple                 | any compatible slice                            | slice size and elements must match
    95  //                        | any compatible array                            | array size and elements must match
    96  //                        | any compatible struct                           | fields must be exported and are marshaled in order of declaration
    97  //  user-defined type     | any compatible map                              | map key must be string
    98  //                        | any compatible struct                           | fields must be exported; field names match case-insensitively (2)
    99  //                        | any compatible slice                            | slice size and elements must match
   100  //                        | any compatible array                            | array size and elements must match
   101  //  uuid, timeuuid        | primitive.UUID, *primitive.UUID                 |
   102  //                        | [16]byte, []byte                                | raw UUID bytes, length must be 16 bytes
   103  //                        | string, *string                                 | hex representation, parsed with primitive.ParseUuid
   104  //  varchar, text, ascii  | string, *string                                 |
   105  //                        | []byte, *[]byte, []rune, *[]rune                |
   106  //  varint                | big.Int, *big.Int                               |
   107  //                        | int[64-8], *int[64-8], uint[64-8], *uint[64-8]  |
   108  //                        | string, *string                                 | formatted and parsed as base 10 number
   109  //
   110  // (1) types listed on the first line are the preferred types for each CQL type. Note that non-pointer types are only
   111  // accepted when encoding, never when decoding.
   112  // (2) when mapping structs to user-defined types, the "cassandra" field tag can be used to override the corresponding
   113  // field name.
   114  //
   115  // In addition to the accepted types above, all codecs also accept interface{} when encoding and *interface{} when
   116  // decoding. When encoding an interface{} value, the actual runtime value stored in the variable must be of an
   117  // accepted type. When decoding to *interface{}, the codec will use the preferred type to decode, then store its value
   118  // in the target variable; if the decoded value was NULL, the target will be set to nil.
   119  //
   120  // Encoding data
   121  //
   122  // Sources can be passed by value or by reference, unless specified otherwise in the table above. Nils are encoded as
   123  // CQL NULLs; encoding such a value is generally a no-op and returns a nil []byte.
   124  //
   125  // Decoding data
   126  //
   127  // Destination values must be passed by reference, see examples below. This is also valid for slices and maps, and is
   128  // required for the value to be addressable (i.e. settable), and for the changes applied to the value to be visible once
   129  // the method returns.
   130  //
   131  // When a CQL NULL is decoded, the passed `dest` variable is set to its zero value. Depending on the variable type, the
   132  // zero value may or may not be distinguishable from the CQL zero value for that type. For example, if a CQL bigint was
   133  // NULL and `dest` is `int64`, then `dest` will be set to `0`, effectively making this indistinguishable from a non-NULL
   134  // bigint value of `0`. This is why the return parameter `wasNull` is used for: if `wasNull` is true then the decoded
   135  // value was a CQL NULL.
   136  //
   137  // A typical invocation of `Codec.Decode` is as follows:
   138  //
   139  //  source := []byte{...}
   140  //  var value int64
   141  //  wasNull, err := datacodec.Bigint.Decode(source, &value, primitive.ProtocolVersion5)
   142  //  if err != nil {
   143  // 	  fmt.Println("Decoding failed: ", err)
   144  //  } else if wasNull {
   145  // 	  fmt.Println("CQL value was NULL")
   146  //  } else {
   147  // 	  fmt.Println("CQL value was:", value)
   148  //  }
   149  //
   150  // Decoding a complex CQL type, such as a list, is not very different:
   151  //
   152  //  source := []byte{...}
   153  //  var value []int
   154  //  listOfInt := datatype.NewListType(datatype.Int)
   155  //  listOfIntCodec, _ := datacodec.NewList(listOfInt)
   156  //  wasNull, err := listOfIntCodec.Decode(source, &value, primitive.ProtocolVersion5)
   157  //  if err != nil {
   158  // 	  fmt.Println("Decoding failed: ", err)
   159  //  } else if wasNull {
   160  // 	  fmt.Println("CQL value was NULL")
   161  //  } else {
   162  // 	  fmt.Println("CQL value was:", value)
   163  //  }
   164  package datacodec