1414
1515#include " extensions/formatting.h"
1616
17+ #include < algorithm>
1718#include < cmath>
1819#include < cstdint>
1920#include < limits>
2021#include < memory>
2122#include < optional>
2223#include < string>
23- #include < tuple>
2424#include < type_traits>
2525#include < utility>
2626
2727#include " absl/base/attributes.h"
2828#include " absl/base/nullability.h"
2929#include " absl/container/btree_map.h"
30- #include " absl/memory/memory.h"
3130#include " absl/numeric/bits.h"
3231#include " absl/status/status.h"
3332#include " absl/status/statusor.h"
@@ -64,7 +63,7 @@ absl::StatusOr<absl::string_view> FormatString(
6463 std::string& scratch ABSL_ATTRIBUTE_LIFETIME_BOUND);
6564
6665absl::StatusOr<std::pair<int64_t , std::optional<int >>> ParsePrecision (
67- absl::string_view format) {
66+ absl::string_view format, int max_precision ) {
6867 if (format.empty () || format[0 ] != ' .' ) return std::pair{0 , std::nullopt };
6968
7069 int64_t i = 1 ;
@@ -80,9 +79,9 @@ absl::StatusOr<std::pair<int64_t, std::optional<int>>> ParsePrecision(
8079 return absl::InvalidArgumentError (
8180 " unable to convert precision specifier to integer" );
8281 }
83- if (precision > kMaxPrecision ) {
82+ if (precision > max_precision ) {
8483 return absl::InvalidArgumentError (
85- absl::StrCat (" precision specifier exceeds maximum of " , kMaxPrecision ));
84+ absl::StrCat (" precision specifier exceeds maximum of " , max_precision ));
8685 }
8786 return std::pair{i, precision};
8887}
@@ -444,12 +443,13 @@ absl::StatusOr<absl::string_view> FormatScientific(
444443}
445444
446445absl::StatusOr<std::pair<int64_t , absl::string_view>> ParseAndFormatClause (
447- absl::string_view format, const Value& value,
446+ absl::string_view format, const Value& value, int max_precision,
448447 const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
449448 google::protobuf::MessageFactory* absl_nonnull message_factory,
450449 google::protobuf::Arena* absl_nonnull arena,
451450 std::string& scratch ABSL_ATTRIBUTE_LIFETIME_BOUND) {
452- CEL_ASSIGN_OR_RETURN (auto precision_pair, ParsePrecision (format));
451+ CEL_ASSIGN_OR_RETURN (auto precision_pair,
452+ ParsePrecision (format, max_precision));
453453 auto [read, precision] = precision_pair;
454454 switch (format[read]) {
455455 case ' s' : {
@@ -494,7 +494,7 @@ absl::StatusOr<std::pair<int64_t, absl::string_view>> ParseAndFormatClause(
494494}
495495
496496absl::StatusOr<Value> Format (
497- const StringValue& format_value, const ListValue& args,
497+ const StringValue& format_value, const ListValue& args, int max_precision,
498498 const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
499499 google::protobuf::MessageFactory* absl_nonnull message_factory,
500500 google::protobuf::Arena* absl_nonnull arena) {
@@ -512,43 +512,50 @@ absl::StatusOr<Value> Format(
512512 }
513513 ++i;
514514 if (i >= format.size ()) {
515- return absl::InvalidArgumentError (" unexpected end of format string" );
515+ return ErrorValue (
516+ absl::InvalidArgumentError (" unexpected end of format string" ));
516517 }
517518 if (format[i] == ' %' ) {
518519 result.push_back (' %' );
519520 continue ;
520521 }
521522 if (arg_index >= args_size) {
522- return absl::InvalidArgumentError (
523- absl::StrFormat (" index %d out of range" , arg_index));
523+ return ErrorValue ( absl::InvalidArgumentError (
524+ absl::StrFormat (" index %d out of range" , arg_index))) ;
524525 }
525526 CEL_ASSIGN_OR_RETURN (auto value, args.Get (arg_index++, descriptor_pool,
526527 message_factory, arena));
527- CEL_ASSIGN_OR_RETURN (
528- auto clause,
529- ParseAndFormatClause (format.substr (i), value, descriptor_pool,
530- message_factory, arena, clause_scratch));
531- absl::StrAppend (&result, clause.second );
532- i += clause.first ;
528+
529+ auto clause = ParseAndFormatClause (format.substr (i), value, max_precision,
530+ descriptor_pool, message_factory, arena,
531+ clause_scratch);
532+ if (!clause.ok ()) {
533+ return ErrorValue (std::move (clause).status ());
534+ }
535+ absl::StrAppend (&result, clause->second );
536+ i += clause->first ;
533537 }
534- return StringValue (arena, std::move (result));
538+ return StringValue::From ( std::move (result), arena );
535539}
536540
537541} // namespace
538542
539543absl::Status RegisterStringFormattingFunctions (FunctionRegistry& registry,
540- const RuntimeOptions& options) {
544+ const RuntimeOptions& options,
545+ int max_precision) {
546+ max_precision = std::clamp (max_precision, 0 , kMaxPrecision );
541547 CEL_RETURN_IF_ERROR (registry.Register (
542548 BinaryFunctionAdapter<absl::StatusOr<Value>, StringValue, ListValue>::
543549 CreateDescriptor (" format" , /* receiver_style=*/ true ),
544550 BinaryFunctionAdapter<absl::StatusOr<Value>, StringValue, ListValue>::
545551 WrapFunction (
546- [](const StringValue& format, const ListValue& args,
547- const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
548- google::protobuf::MessageFactory* absl_nonnull message_factory,
549- google::protobuf::Arena* absl_nonnull arena) {
550- return Format (format, args, descriptor_pool, message_factory,
551- arena);
552+ [max_precision](
553+ const StringValue& format, const ListValue& args,
554+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
555+ google::protobuf::MessageFactory* absl_nonnull message_factory,
556+ google::protobuf::Arena* absl_nonnull arena) {
557+ return Format (format, args, max_precision, descriptor_pool,
558+ message_factory, arena);
552559 })));
553560 return absl::OkStatus ();
554561}
0 commit comments