xref: /aosp_15_r20/external/webrtc/net/dcsctp/packet/bounded_byte_reader.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
12 #define NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
13 
14 #include <cstdint>
15 
16 #include "api/array_view.h"
17 
18 namespace dcsctp {
19 
20 // TODO(boivie): These generic functions - and possibly this entire class -
21 // could be a candidate to have added to rtc_base/. They should use compiler
22 // intrinsics as well.
23 namespace internal {
24 // Loads a 8-bit unsigned word at `data`.
LoadBigEndian8(const uint8_t * data)25 inline uint8_t LoadBigEndian8(const uint8_t* data) {
26   return data[0];
27 }
28 
29 // Loads a 16-bit unsigned word at `data`.
LoadBigEndian16(const uint8_t * data)30 inline uint16_t LoadBigEndian16(const uint8_t* data) {
31   return (data[0] << 8) | data[1];
32 }
33 
34 // Loads a 32-bit unsigned word at `data`.
LoadBigEndian32(const uint8_t * data)35 inline uint32_t LoadBigEndian32(const uint8_t* data) {
36   return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
37 }
38 }  // namespace internal
39 
40 // BoundedByteReader wraps an ArrayView and divides it into two parts; A fixed
41 // size - which is the template parameter - and a variable size, which is what
42 // remains in `data` after the `FixedSize`.
43 //
44 // The BoundedByteReader provides methods to load/read big endian numbers from
45 // the FixedSize portion of the buffer, and these are read with static bounds
46 // checking, to avoid out-of-bounds accesses without a run-time penalty.
47 //
48 // The variable sized portion can either be used to create sub-readers, which
49 // themselves would provide compile-time bounds-checking, or the entire variable
50 // sized portion can be retrieved as an ArrayView.
51 template <int FixedSize>
52 class BoundedByteReader {
53  public:
BoundedByteReader(rtc::ArrayView<const uint8_t> data)54   explicit BoundedByteReader(rtc::ArrayView<const uint8_t> data) : data_(data) {
55     RTC_CHECK(data.size() >= FixedSize);
56   }
57 
58   template <size_t offset>
Load8()59   uint8_t Load8() const {
60     static_assert(offset + sizeof(uint8_t) <= FixedSize, "Out-of-bounds");
61     return internal::LoadBigEndian8(&data_[offset]);
62   }
63 
64   template <size_t offset>
Load16()65   uint16_t Load16() const {
66     static_assert(offset + sizeof(uint16_t) <= FixedSize, "Out-of-bounds");
67     static_assert((offset % sizeof(uint16_t)) == 0, "Unaligned access");
68     return internal::LoadBigEndian16(&data_[offset]);
69   }
70 
71   template <size_t offset>
Load32()72   uint32_t Load32() const {
73     static_assert(offset + sizeof(uint32_t) <= FixedSize, "Out-of-bounds");
74     static_assert((offset % sizeof(uint32_t)) == 0, "Unaligned access");
75     return internal::LoadBigEndian32(&data_[offset]);
76   }
77 
78   template <size_t SubSize>
sub_reader(size_t variable_offset)79   BoundedByteReader<SubSize> sub_reader(size_t variable_offset) const {
80     RTC_CHECK(FixedSize + variable_offset + SubSize <= data_.size());
81 
82     rtc::ArrayView<const uint8_t> sub_span =
83         data_.subview(FixedSize + variable_offset, SubSize);
84     return BoundedByteReader<SubSize>(sub_span);
85   }
86 
variable_data_size()87   size_t variable_data_size() const { return data_.size() - FixedSize; }
88 
variable_data()89   rtc::ArrayView<const uint8_t> variable_data() const {
90     return data_.subview(FixedSize, data_.size() - FixedSize);
91   }
92 
93  private:
94   const rtc::ArrayView<const uint8_t> data_;
95 };
96 
97 }  // namespace dcsctp
98 
99 #endif  // NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
100