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