Make conversion from `{String,Bytes,Path}Ref` to `absl::string_view` explicit.
Same for conversion from `{Bytes,Path}Ref` to `StringRef`. Conversions in the
other direction remain implicit.

Mutual implicit conversions are prone to ambiguities, e.g. in heterogeneous
calls to `==`.

Comparisons are especially problematic, as subtleties of overload resolution
depend on whether secondary comparison operators are derived automatically
in C++20 or emulated in C++17 with `WithEqual` and `WithCompare`. If primary
comparison operators have concrete parameter types, then C++20 provides
secondary comparison operators with the same parameter types, for which argument
conversions happen in the caller, while C++17 emulataion provides templates for
which argument conversions happen in the callee.

Types `StringRef` etc. are designed for function parameters. It is important
that they accept any suitable argument, i.e. conversions to them are important
to be implicit. OTOH consuming these parameters can be less convenient, and
conversions from them can be explicit.

Let `BytesRef` and `PathRef` derive from `StringRefBase` extracted from
`StringRef` rather than from `StringRef` itself. The latter would make
`BytesRef` implicitly convertible to `StringRef`, while we prefer
the other direction: `BytesRef` accepts more types than `StringRef`, e.g.
`Span<const char>`, so `BytesRef` should accept `StringRef` instead of
the other way around.

Make `CStringRef` convertible from types convertible to `std::string`, e.g.
`StringInitializer`. This improves compatibility with `StringRef`.

Polish constructors of `StringRef` etc.:

* Accept view types by value. This lets `ABSL_ATTRIBUTE_LIFETIME_BOUND` apply
  only to what the view is constructed from, but not to the view object itself.
  The view can safely be a temporary. Also, this reduces template instantiations
  in common usages.

* Remove `ABSL_ATTRIBUTE_LIFETIME_BOUND` where the parameter reference is not
  actually retained because its data have been just copied to `std::string`.

* Constrain templates by types being convertible to `absl::string_view` rather
  than to `StringRef` etc. The latter conversions may keep data in defaulted
  arguments, which do not survive forwarding, so they should not be used inside
  implementations of other conversions to view types.

Coalesce comments about the constructors. A single comment states the goal of
multiple constructors, rather than details of the order of conversions and
materialization by each constructor. The details are not that important,
and the expectations about arguments are already stated in class comments.

Make `BytesRef` comparable only against itself, and make `CompactString`
and `OptionalCompactString` comparable against `absl::string_view` but not
`BytesRef`. While this disallows direct comparisons between e.g. `CompactString`
and `std::array<char, length>`, this reduces ambiguities in cases like
`CompactString == StringRef`. Arbitrary types convertible to `BytesRef`
are not necessarily comparable anyway, e.g. `std::string` against
`std::array<char, length>`, so `CompactString` does not need to cover that.

`BytesRef` remains implicitly convertible both from and to
`absl::Span<const char>`. This is hard to avoid because `absl::Span<const char>`
is convertible from any type providing suitable `data()` and `size()`,
which includes `BytesRef`.

`BytesRef` cannot be reliably compared against `absl::Span<const char>` in C++17
mode. This is so because `absl::Span` provides a comparison against any type
convertible to `absl::Span`, which is ambiguous wrt. comparisons provided by
`WithCompare<BytesRef>`. It is comparable in C++20 mode though, because overload
resolution prefers templated operators provided by `Span` over converting `Span`
to `BytesRef` on the caller side.

PiperOrigin-RevId: 900626152
25 files changed
tree: a7561c257c1bb747c9164f19857db592b6875a17
  1. doc/
  2. python/
  3. riegeli/
  4. tf_dependency/
  5. .bazelrc
  6. configure
  7. CONTRIBUTING.md
  8. LICENSE
  9. MANIFEST.in
  10. MODULE.bazel
  11. README.md
README.md

Riegeli

Riegeli/records is a file format for storing a sequence of string records, typically serialized protocol buffers. It supports dense compression, fast decoding, seeking, detection and optional skipping of data corruption, filtering of proto message fields for even faster decoding, and parallel encoding.

See documentation.

Status

Riegeli file format will only change in a backward compatible way (i.e. future readers will understand current files, but current readers might not understand files using future features).

Riegeli C++ API might change in incompatible ways.