github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/segment/segment.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 segment 16 17 import ( 18 "bytes" 19 "encoding/hex" 20 "fmt" 21 ) 22 23 // Segment is a checksummed payload containing one or more frames (self-contained segment), or just a portion of a 24 // larger frame spanning multiple segments (multi-segment part). It can also be optionally compressed with Lz4. 25 // Segments were introduced in protocol v5 to improve compression efficiency (especially for small messages) and to 26 // introduce error detection in the native protocol. 27 // +k8s:deepcopy-gen=true 28 type Segment struct { 29 Header *Header 30 Payload *Payload 31 } 32 33 // Header is the header of a Segment. 34 // +k8s:deepcopy-gen=true 35 type Header struct { 36 // IsSelfContained is true when this segment's payload contains one or more Frames (self-contained segment); when it 37 // is false, this segment's payload contains just a portion of a larger frame spanning multiple segments 38 // (multi-segment part). 39 IsSelfContained bool 40 // UncompressedPayloadLength is the length of the uncompressed payload data. The value of this field should always 41 // be equal to the length of Payload.UncompressedData. This is a computed value that users should not set 42 // themselves. When encoding a segment, this field is not read but is rather dynamically computed from the actual 43 // payload length. When decoding a segment, this field is always correctly set to the exact decoded payload length. 44 UncompressedPayloadLength int32 45 // CompressedPayloadLength is the length of the compressed payload data, if compression is being used; it is 0 46 // otherwise. This is a computed value that users should not set themselves. When encoding a segment, this field is 47 // not read but is rather dynamically computed from the actual compressed payload length. When decoding a segment, 48 // this field is always correctly set to the exact compressed payload length. 49 CompressedPayloadLength int32 50 // Crc24 is the CRC-24 checksum of the encoded header. This is a computed value that users should not set 51 // themselves. When encoding a segment, this field is not read but is rather dynamically computed from the actual 52 // encoded header. When decoding a segment, the CRC-24 present in the header trailer is verified against that of 53 // the actual decoded header, then set to that value if it matches. 54 Crc24 uint32 55 } 56 57 // Payload is the payload of a Segment. 58 // +k8s:deepcopy-gen=true 59 type Payload struct { 60 // UncompressedData holds the uncompressed data forming one or more frames. 61 UncompressedData []byte 62 // Crc32 is the CRC-32 checksum of the payload. This is a computed value that users should not set 63 // themselves. When encoding a segment, this field is not read but is rather dynamically computed from the actual 64 // payload. When decoding a segment, the CRC-32 present in the payload trailer is verified against the actual 65 // decoded payload, then set to that value if it matches. 66 Crc32 uint32 67 } 68 69 func (s *Segment) String() string { 70 return fmt.Sprintf("{header: %v, payload: %v}", s.Header, s.Payload) 71 } 72 73 func (h *Header) String() string { 74 return fmt.Sprintf( 75 "{self-contained: %v, uncompressed length: %v, compressed length: %v, crc24: %v}", 76 h.IsSelfContained, 77 h.UncompressedPayloadLength, 78 h.CompressedPayloadLength, 79 h.Crc24, 80 ) 81 } 82 83 func (p *Payload) String() string { 84 return fmt.Sprintf("{length: %v, crc32: %v}", len(p.UncompressedData), p.Crc32) 85 } 86 87 // Dump encodes and dumps the contents of this segment, for debugging purposes. 88 func (s *Segment) Dump() (string, error) { 89 buffer := bytes.Buffer{} 90 if err := NewCodec().EncodeSegment(s, &buffer); err != nil { 91 return "", err 92 } else { 93 return hex.Dump(buffer.Bytes()), nil 94 } 95 }