1414
1515#include " policy/yaml_policy_parser.h"
1616
17+ #include < cstddef>
1718#include < memory>
1819#include < optional>
1920#include < string>
2021#include < utility>
22+ #include < vector>
2123
2224#include " absl/status/status.h"
2325#include " absl/status/statusor.h"
2426#include " absl/strings/str_cat.h"
2527#include " absl/strings/string_view.h"
2628#include " common/source.h"
2729#include " internal/status_macros.h"
30+ #include " internal/utf8.h"
2831#include " policy/cel_policy.h"
2932#include " policy/cel_policy_parse_context.h"
3033#include " policy/cel_policy_parse_result.h"
3134#include " policy/cel_policy_parser.h"
3235#include " policy/internal/yaml_string_element_scanner.h"
3336#include " yaml-cpp/exceptions.h"
37+ #include " yaml-cpp/mark.h"
3438#include " yaml-cpp/node/node.h"
3539#include " yaml-cpp/node/parse.h"
3640#include " yaml-cpp/null.h"
3741#include " yaml-cpp/yaml.h" // IWYU pragma: keep
3842
3943namespace cel {
44+ namespace {
45+
46+ SourcePosition GetMarkCodepointPosition (const CelPolicyParseContext& ctx,
47+ const YAML ::Mark& mark) {
48+ if (mark.is_null () || mark.pos < 0 ) return -1 ;
49+ return ctx.GetCodepointPosition (mark.pos );
50+ }
51+
52+ } // namespace
4053
4154CelPolicyElementId YamlPolicyParser::CollectMetadata (
4255 CelPolicyParseContext& ctx, const YAML ::Node& node) const {
4356 CelPolicyElementId element_id = ctx.next_element_id ();
4457 if (!node.Mark ().is_null ()) {
45- ctx.policy_source ().NoteSourcePosition (element_id, node.Mark ().pos );
58+ ctx.policy_source ().NoteSourcePosition (
59+ element_id, GetMarkCodepointPosition (ctx, node.Mark ()));
4660 }
4761 return element_id;
4862}
@@ -62,9 +76,10 @@ std::optional<ValueString> YamlPolicyParser::GetValueString(
6276 }
6377
6478 if (!node.Mark ().is_null () && ctx.policy_source ().content () != nullptr ) {
79+ SourcePosition codepoint_pos = GetMarkCodepointPosition (ctx, node.Mark ());
6580 policy_internal::YamlStringElement element =
6681 policy_internal::ScanYamlStringElement (
67- ctx.policy_source ().content ()->content (), node. Mark (). pos ,
82+ ctx.policy_source ().content ()->content (), codepoint_pos ,
6883 node.as <std::string>());
6984
7085 ctx.policy_source ().NoteSourcePosition (id, element.starting_position );
@@ -87,14 +102,40 @@ absl::Status YamlPolicyParser::ParsePolicy(CelPolicyParseContext& ctx) const {
87102 return absl::OkStatus ();
88103 }
89104
90- ctx.policy ().set_description (ValueString (-1 , source->description ()));
105+ // TODO(b/542282964): Fold this mapping into cel::Source decoding happens
106+ // once.
91107 std::string text = source->content ().ToString ();
108+ std::vector<SourcePosition> mapping;
109+ mapping.resize (text.size () + 1 , 0 );
110+ size_t byte_offset = 0 ;
111+ SourcePosition codepoint = 0 ;
112+ absl::string_view view = text;
113+ while (!view.empty ()) {
114+ auto [code_point, code_units] = cel::internal::Utf8Decode (view);
115+ if (code_units == 0 ) break ;
116+ for (size_t i = 0 ; i < code_units; ++i) {
117+ if (byte_offset + i < mapping.size ()) {
118+ mapping[byte_offset + i] = codepoint;
119+ }
120+ }
121+ byte_offset += code_units;
122+ view.remove_prefix (code_units);
123+ codepoint++;
124+ }
125+ for (size_t i = byte_offset; i < mapping.size (); ++i) {
126+ mapping[i] = codepoint;
127+ }
128+
129+ ctx.set_byte_to_codepoint_mapping (std::move (mapping));
130+
131+ ctx.policy ().set_description (ValueString (-1 , source->description ()));
92132 YAML ::Node node;
93133 try {
94134 node = YAML::Load (text);
95135 } catch (YAML ::Exception& e) {
96136 if (!e.mark .is_null ()) {
97- ctx.policy_source ().NoteSourcePosition (0 , e.mark .pos );
137+ ctx.policy_source ().NoteSourcePosition (
138+ 0 , GetMarkCodepointPosition (ctx, e.mark ));
98139 }
99140 ctx.ReportError (0 , " Invalid CEL policy YAML syntax" );
100141 return absl::OkStatus ();
0 commit comments