1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cassert> 20 #include <cstdint> 21 #include <memory> 22 #include <utility> 23 #include <vector> 24 25 namespace pdl::packet { 26 27 /// Representation of a raw packet slice. 28 /// The slice contains a shared pointer to the source packet bytes, and points 29 /// to a subrange within this byte buffer. 30 class slice { 31 public: 32 slice() = default; 33 slice(slice const&) = default; slice(std::shared_ptr<const std::vector<uint8_t>> packet)34 slice(std::shared_ptr<const std::vector<uint8_t>> packet) 35 : packet_(std::move(packet)), offset_(0), size_(packet_->size()) {} 36 slice(std::shared_ptr<const std::vector<uint8_t>> packet,size_t offset,size_t size)37 slice(std::shared_ptr<const std::vector<uint8_t>> packet, size_t offset, 38 size_t size) 39 : packet_(std::move(packet)), offset_(offset), size_(size) {} 40 41 /// Return a new slice that contains the selected subrange within the 42 /// current slice. The range ['offset', 'offset' + 'slice') must be 43 /// contained within the bonuds of the current slice. subrange(size_t offset,size_t size)44 slice subrange(size_t offset, size_t size) const { 45 assert((offset + size) <= size_); 46 return slice(packet_, offset_ + offset, size); 47 } 48 49 /// Read a scalar value encoded in little-endian. 50 /// The bytes that are read from calling this function are consumed. 51 /// This function can be used to iterativaly extract values from a packet 52 /// slice. 53 template <typename T, size_t N = sizeof(T)> read_le()54 T read_le() { 55 static_assert(N <= sizeof(T)); 56 assert(N <= size_); 57 T value = 0; 58 for (size_t n = 0; n < N; n++) { 59 value |= (T)at(n) << (8 * n); 60 } 61 skip(N); 62 return value; 63 } 64 65 /// Read a scalar value encoded in big-endian. 66 /// The bytes that are read from calling this function are consumed. 67 /// This function can be used to iterativaly extract values from a packet 68 /// slice. 69 template <typename T, size_t N = sizeof(T)> read_be()70 T read_be() { 71 static_assert(N <= sizeof(T)); 72 assert(N <= size_); 73 T value = 0; 74 for (size_t n = 0; n < N; n++) { 75 value = (value << 8) | (T)at(n); 76 } 77 skip(N); 78 return value; 79 } 80 81 /// Return the value of the byte at the given offset. 82 /// `offset` must be within the bounds of the slice. at(size_t offset)83 uint8_t at(size_t offset) const { 84 assert(offset <= size_); 85 return packet_->at(offset_ + offset); 86 } 87 88 /// Skip `size` bytes at the front of the slice. 89 /// `size` must be lower than or equal to the slice size. skip(size_t size)90 void skip(size_t size) { 91 assert(size <= size_); 92 offset_ += size; 93 size_ -= size; 94 } 95 96 /// Empty the slice. clear()97 void clear() { size_ = 0; } 98 99 /// Return the size of the slice in bytes. size()100 size_t size() const { return size_; } 101 102 /// Return the contents of the slice as a byte vector. bytes()103 std::vector<uint8_t> bytes() const { 104 return std::vector<uint8_t>(packet_->cbegin() + offset_, 105 packet_->cbegin() + offset_ + size_); 106 } 107 108 bool operator==(slice const& other) const { 109 return size_ == other.size_ && 110 std::equal(packet_->begin() + offset_, 111 packet_->begin() + offset_ + size_, 112 other.packet_->begin()); 113 } 114 115 private: 116 std::shared_ptr<const std::vector<uint8_t>> packet_; 117 size_t offset_{0}; 118 size_t size_{0}; 119 }; 120 121 /// Interface class for generated packet builders. 122 class Builder { 123 public: 124 virtual ~Builder() = default; 125 126 /// Method implemented by generated packet builders. 127 /// The packet fields are concatenated to the output vector. Serialize(std::vector<uint8_t> &)128 virtual void Serialize(std::vector<uint8_t>&) const {} 129 130 /// Method implemented by generated packet builders. 131 /// Returns the size of the serialized packet in bytes. GetSize()132 virtual size_t GetSize() const { return 0; } 133 134 /// Write a scalar value encoded in little-endian. 135 template <typename T, size_t N = sizeof(T)> write_le(std::vector<uint8_t> & output,T value)136 static void write_le(std::vector<uint8_t>& output, T value) { 137 static_assert(N <= sizeof(T)); 138 for (size_t n = 0; n < N; n++) { 139 output.push_back(value >> (8 * n)); 140 } 141 } 142 143 /// Write a scalar value encoded in big-endian. 144 template <typename T, size_t N = sizeof(T)> write_be(std::vector<uint8_t> & output,T value)145 static void write_be(std::vector<uint8_t>& output, T value) { 146 static_assert(N <= sizeof(T)); 147 for (size_t n = 0; n < N; n++) { 148 output.push_back(value >> (8 * (N - 1 - n))); 149 } 150 } 151 152 /// Helper method to serialize the packet to a byte vector. SerializeToBytes()153 virtual std::vector<uint8_t> SerializeToBytes() const { 154 std::vector<uint8_t> output; 155 Serialize(output); 156 return output; 157 } 158 }; 159 160 } // namespace pdl::packet 161