• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_DER_INPUT_H_
6 #define NET_DER_INPUT_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <string>
12 
13 #include "base/containers/span.h"
14 #include "net/base/net_export.h"
15 
16 namespace net::der {
17 
18 // An opaque class that represents a fixed buffer of data of a fixed length,
19 // to be used as an input to other operations. An Input object does not own
20 // the data it references, so callers are responsible for making sure that
21 // the data outlives the Input object and any other associated objects.
22 //
23 // All data access for an Input should be done through the ByteReader class.
24 // This class and associated classes are designed with safety in mind to make it
25 // difficult to read memory outside of an Input. ByteReader provides a simple
26 // API for reading through the Input sequentially. For more complicated uses,
27 // multiple instances of a ByteReader for a particular Input can be created.
28 class NET_EXPORT_PRIVATE Input {
29  public:
30   // Creates an empty Input, one from which no data can be read.
31   constexpr Input() = default;
32 
33   // Creates an Input from a constant array |data|.
34   template <size_t N>
Input(const uint8_t (& data)[N])35   constexpr explicit Input(const uint8_t (&data)[N]) : data_(data), len_(N) {}
36 
37   // Creates an Input from the given |data| and |len|.
Input(const uint8_t * data,size_t len)38   constexpr explicit Input(const uint8_t* data, size_t len)
39       : data_(data), len_(len) {}
40 
41   // Creates an Input from a std::string_view
42   explicit Input(std::string_view sp);
43 
44   // Creates an Input from a std::string. The lifetimes are a bit subtle when
45   // using this function: The constructed Input is only valid so long as |s| is
46   // still alive and not mutated.
47   explicit Input(const std::string* s);
48 
49   // Returns the length in bytes of an Input's data.
Length()50   constexpr size_t Length() const { return len_; }
51 
52   // Returns a pointer to the Input's data. This method is marked as "unsafe"
53   // because access to the Input's data should be done through ByteReader
54   // instead. This method should only be used where using a ByteReader truly
55   // is not an option.
UnsafeData()56   constexpr const uint8_t* UnsafeData() const { return data_; }
57 
58   // Returns a copy of the data represented by this object as a std::string.
59   std::string AsString() const;
60 
61   // Returns a std::string_view pointing to the same data as the Input. The
62   // resulting string_view must not outlive the data that was used to construct
63   // this Input.
64   std::string_view AsStringView() const;
65 
66   // Returns a base::span pointing to the same data as the Input. The resulting
67   // base::span must not outlive the data that was used to construct this
68   // Input.
69   base::span<const uint8_t> AsSpan() const;
70 
71  private:
72   // This constructor is deleted to prevent constructing an Input from a
73   // std::string r-value. Since the Input points to memory owned by another
74   // object, such an Input would point to invalid memory. Without this deleted
75   // constructor, a std::string could be passed in to the base::StringPiece
76   // constructor because of StringPiece's implicit constructor.
77   Input(std::string) = delete;
78 
79   const uint8_t* data_ = nullptr;
80   size_t len_ = 0;
81 };
82 
83 // Return true if |lhs|'s data and |rhs|'s data are byte-wise equal.
84 NET_EXPORT_PRIVATE bool operator==(const Input& lhs, const Input& rhs);
85 
86 // Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal.
87 NET_EXPORT_PRIVATE bool operator!=(const Input& lhs, const Input& rhs);
88 
89 // Returns true if |lhs|'s data is lexicographically less than |rhs|'s data.
90 NET_EXPORT_PRIVATE constexpr bool operator<(const Input& lhs,
91                                             const Input& rhs) {
92   // This is `std::lexicographical_compare`, but that's not `constexpr` until
93   // C++-20.
94   auto* it1 = lhs.UnsafeData();
95   auto* it2 = rhs.UnsafeData();
96   const auto* end1 = lhs.UnsafeData() + lhs.Length();
97   const auto* end2 = rhs.UnsafeData() + rhs.Length();
98   for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
99     if (*it1 < *it2) {
100       return true;
101     } else if (*it2 < *it1) {
102       return false;
103     }
104   }
105 
106   return it2 != end2;
107 }
108 
109 // This class provides ways to read data from an Input in a bounds-checked way.
110 // The ByteReader is designed to read through the input sequentially. Once a
111 // byte has been read with a ByteReader, the caller can't go back and re-read
112 // that byte with the same reader. Of course, the caller can create multiple
113 // ByteReaders for the same input (or copy an existing ByteReader).
114 //
115 // For something simple like a single byte lookahead, the easiest way to do
116 // that is to copy the ByteReader and call ReadByte() on the copy - the original
117 // ByteReader will be unaffected and the peeked byte will be read through
118 // ReadByte(). For other read patterns, it can be useful to mark where one is
119 // in a ByteReader to be able to return to that spot.
120 //
121 // Some operations using Mark can also be done by creating a copy of the
122 // ByteReader. By using a Mark instead, you use less memory, but more
123 // importantly, you end up with an immutable object that matches the semantics
124 // of what is intended.
125 class NET_EXPORT_PRIVATE ByteReader {
126  public:
127   // Creates a ByteReader to read the data represented by an Input.
128   explicit ByteReader(const Input& in);
129 
130   // Reads a single byte from the input source, putting the byte read in
131   // |*byte_p|. If a byte cannot be read from the input (because there is
132   // no input left), then this method returns false.
133   [[nodiscard]] bool ReadByte(uint8_t* out);
134 
135   // Reads |len| bytes from the input source, and initializes an Input to
136   // point to that data. If there aren't enough bytes left in the input source,
137   // then this method returns false.
138   [[nodiscard]] bool ReadBytes(size_t len, Input* out);
139 
140   // Returns how many bytes are left to read.
BytesLeft()141   size_t BytesLeft() const { return len_; }
142 
143   // Returns whether there is any more data to be read.
144   bool HasMore();
145 
146  private:
147   void Advance(size_t len);
148 
149   const uint8_t* data_;
150   size_t len_;
151 };
152 
153 }  // namespace net::der
154 
155 #endif  // NET_DER_INPUT_H_
156