| 494 | } |
| 495 | |
| 496 | absl::StatusOr<Value> Format( |
| 497 | const StringValue& format_value, const ListValue& args, int max_precision, |
| 498 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
| 499 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
| 500 | google::protobuf::Arena* absl_nonnull arena) { |
| 501 | std::string format_scratch, clause_scratch; |
| 502 | absl::string_view format = format_value.NativeString(format_scratch); |
| 503 | std::string result; |
| 504 | result.reserve(format.size()); |
| 505 | int64_t arg_index = 0; |
| 506 | CEL_ASSIGN_OR_RETURN(int64_t args_size, args.Size()); |
| 507 | for (int64_t i = 0; i < format.size(); ++i) { |
| 508 | clause_scratch.clear(); |
| 509 | if (format[i] != '%') { |
| 510 | result.push_back(format[i]); |
| 511 | continue; |
| 512 | } |
| 513 | ++i; |
| 514 | if (i >= format.size()) { |
| 515 | return ErrorValue( |
| 516 | absl::InvalidArgumentError("unexpected end of format string")); |
| 517 | } |
| 518 | if (format[i] == '%') { |
| 519 | result.push_back('%'); |
| 520 | continue; |
| 521 | } |
| 522 | if (arg_index >= args_size) { |
| 523 | return ErrorValue(absl::InvalidArgumentError( |
| 524 | absl::StrFormat("index %d out of range", arg_index))); |
| 525 | } |
| 526 | CEL_ASSIGN_OR_RETURN(auto value, args.Get(arg_index++, descriptor_pool, |
| 527 | message_factory, arena)); |
| 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; |
| 537 | } |
| 538 | return StringValue::From(std::move(result), arena); |
| 539 | } |
| 540 | |
| 541 | } // namespace |
| 542 | |