Coverage Report

Created: 2026-07-11 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/source.h
Line
Count
Source
1
// Copyright 2023 Google LLC
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
//     https://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
#ifndef THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_
16
#define THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_
17
18
#include <cstdint>
19
#include <memory>
20
#include <string>
21
#include <utility>
22
23
#include "absl/base/attributes.h"
24
#include "absl/base/nullability.h"
25
#include "absl/container/inlined_vector.h"
26
#include "absl/status/statusor.h"
27
#include "absl/strings/cord.h"
28
#include "absl/strings/string_view.h"
29
#include "absl/types/optional.h"
30
#include "absl/types/span.h"
31
#include "absl/types/variant.h"
32
33
namespace cel {
34
35
namespace common_internal {
36
class SourceImpl;
37
}  // namespace common_internal
38
39
class Source;
40
class SourceSubrange;
41
42
// SourcePosition represents an offset in source text.
43
using SourcePosition = int32_t;
44
45
// SourceRange represents a range of positions, where `begin` is inclusive and
46
// `end` is exclusive.
47
struct SourceRange final {
48
  SourcePosition begin = -1;
49
  SourcePosition end = -1;
50
};
51
52
0
inline bool operator==(const SourceRange& lhs, const SourceRange& rhs) {
53
0
  return lhs.begin == rhs.begin && lhs.end == rhs.end;
54
0
}
55
56
0
inline bool operator!=(const SourceRange& lhs, const SourceRange& rhs) {
57
0
  return !operator==(lhs, rhs);
58
0
}
59
60
// `SourceLocation` is a representation of a line and column in source text.
61
struct SourceLocation final {
62
  int32_t line = -1;    // 1-based line number.
63
  int32_t column = -1;  // 0-based column number.
64
};
65
66
0
inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) {
67
0
  return lhs.line == rhs.line && lhs.column == rhs.column;
68
0
}
69
70
0
inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) {
71
0
  return !operator==(lhs, rhs);
72
0
}
73
74
// `SourceContentView` is a view of the content owned by `Source`, which is a
75
// sequence of Unicode code points.
76
class SourceContentView final {
77
 public:
78
  SourceContentView(const SourceContentView&) = default;
79
  SourceContentView(SourceContentView&&) = default;
80
  SourceContentView& operator=(const SourceContentView&) = default;
81
  SourceContentView& operator=(SourceContentView&&) = default;
82
83
  SourcePosition size() const;
84
85
  bool empty() const;
86
87
  char32_t at(SourcePosition position) const;
88
89
  std::string ToString(SourcePosition begin, SourcePosition end) const;
90
148k
  std::string ToString(SourcePosition begin) const {
91
148k
    return ToString(begin, size());
92
148k
  }
93
0
  std::string ToString() const { return ToString(0); }
94
95
  void AppendToString(std::string& dest) const;
96
97
 private:
98
  friend class Source;
99
  friend class SourceSubrange;
100
101
0
  constexpr SourceContentView() = default;
102
103
  constexpr explicit SourceContentView(absl::Span<const char> view)
104
152k
      : view_(view) {}
105
106
  constexpr explicit SourceContentView(absl::Span<const uint8_t> view)
107
9.14k
      : view_(view) {}
108
109
  constexpr explicit SourceContentView(absl::Span<const char16_t> view)
110
26.6k
      : view_(view) {}
111
112
  constexpr explicit SourceContentView(absl::Span<const char32_t> view)
113
24.1k
      : view_(view) {}
114
115
  absl::variant<absl::Span<const char>, absl::Span<const uint8_t>,
116
                absl::Span<const char16_t>, absl::Span<const char32_t>>
117
      view_;
118
};
119
120
// `Source` represents the source expression.
121
class Source {
122
 public:
123
  using ContentView = SourceContentView;
124
125
  Source(const Source&) = delete;
126
  Source(Source&&) = delete;
127
128
21.6k
  virtual ~Source() = default;
129
130
  Source& operator=(const Source&) = delete;
131
  Source& operator=(Source&&) = delete;
132
133
  virtual absl::string_view description() const
134
      ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
135
136
  // Maps a `SourcePosition` to a `SourceLocation`. Returns an empty
137
  // `absl::optional` when `SourcePosition` is invalid or the information
138
  // required to perform the mapping is not present.
139
  absl::optional<SourceLocation> GetLocation(SourcePosition position) const;
140
141
  // Maps a `SourceLocation` to a `SourcePosition`. Returns an empty
142
  // `absl::optional` when `SourceLocation` is invalid or the information
143
  // required to perform the mapping is not present.
144
  absl::optional<SourcePosition> GetPosition(
145
      const SourceLocation& location) const;
146
147
  absl::optional<std::string> Snippet(int32_t line) const;
148
149
  // Formats an annotated snippet highlighting an error at location, e.g.
150
  //
151
  // "\n | $SOURCE_SNIPPET" +
152
  // "\n | .......^"
153
  //
154
  // Returns an empty string if location is not a valid location in this source.
155
  std::string DisplayErrorLocation(SourceLocation location) const;
156
157
  // Returns a view of the underlying expression text, if present.
158
  virtual ContentView content() const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
159
160
  // Returns a `absl::Span` of `SourcePosition` which represent the positions
161
  // where new lines occur.
162
  virtual absl::Span<const SourcePosition> line_offsets() const
163
      ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
164
165
 protected:
166
0
  static constexpr ContentView EmptyContentView() { return ContentView(); }
167
152k
  static constexpr ContentView MakeContentView(absl::Span<const char> view) {
168
152k
    return ContentView(view);
169
152k
  }
170
9.14k
  static constexpr ContentView MakeContentView(absl::Span<const uint8_t> view) {
171
9.14k
    return ContentView(view);
172
9.14k
  }
173
  static constexpr ContentView MakeContentView(
174
26.6k
      absl::Span<const char16_t> view) {
175
26.6k
    return ContentView(view);
176
26.6k
  }
177
  static constexpr ContentView MakeContentView(
178
24.1k
      absl::Span<const char32_t> view) {
179
24.1k
    return ContentView(view);
180
24.1k
  }
181
182
 private:
183
  friend class common_internal::SourceImpl;
184
  friend class SourceSubrange;
185
186
21.6k
  Source() = default;
187
188
  absl::optional<SourcePosition> FindLinePosition(int32_t line) const;
189
190
  absl::optional<std::pair<int32_t, SourcePosition>> FindLine(
191
      SourcePosition position) const;
192
};
193
194
// `SourceSubrange` is a view of a subrange fo an underlying `Source` object.
195
// Intended to be used when the CEL expression is embedded in a larger text
196
// representation (such as a.celpolicy).
197
//
198
// The parent `Source` must outlive this object.
199
class SourceSubrange final : public Source {
200
 public:
201
  SourceSubrange(const Source& source ABSL_ATTRIBUTE_LIFETIME_BOUND,
202
                 SourceRange range);
203
204
0
  absl::string_view description() const ABSL_ATTRIBUTE_LIFETIME_BOUND override {
205
0
    return source_.description();
206
0
  }
207
208
  // Returns a view of the underlying expression text.
209
  ContentView content() const ABSL_ATTRIBUTE_LIFETIME_BOUND override;
210
211
  // Returns a `absl::Span` of `SourcePosition` which represent the positions
212
  // where new lines occur.
213
  absl::Span<const SourcePosition> line_offsets() const
214
      ABSL_ATTRIBUTE_LIFETIME_BOUND override;
215
216
 private:
217
  const Source& source_;
218
  SourceRange range_;
219
  absl::InlinedVector<SourcePosition, 1> line_offsets_;
220
};
221
222
using SourcePtr = std::unique_ptr<Source>;
223
224
absl::StatusOr<absl_nonnull SourcePtr> NewSource(
225
    absl::string_view content, std::string description = "<input>");
226
227
absl::StatusOr<absl_nonnull SourcePtr> NewSource(
228
    const absl::Cord& content, std::string description = "<input>");
229
230
}  // namespace cel
231
232
#endif  // THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_