blob: 79385871bc00f750d9290c1506dfe0b57e1bd1e4 [file] [log] [blame] [view]
# Emboss C++ Generated Code Reference
## `struct`s
A `struct` will have a corresponding view class, and functions to create views.
### <code>Make*Struct*View</code> free function
```c++
template <typename T>
auto MakeStructView(/* view parameters, */ T *data, size_t size);
```
```c++
template <typename T>
auto MakeStructView(/* view parameters, */ T *container);
```
*`Struct`* will be replaced by the name of the specific `struct` whose view
will be constructed; for example, to make a view for `struct Message`, call the
`MakeMessageView` function.
*View parameters* will be replaced by one argument for each parameter attached
to the `struct`. E.g., for:
```
struct Foo(x: UInt:8):
--
```
`MakeFooView` will be:
```c++
template <typename T>
auto MakeFooView(std::uint8_t x, T *data, size_t size);
```
```c++
template <typename T>
auto MakeFooView(std::uint8_t x, T *container);
```
And for:
```
struct Bar(x: UInt:8, y: Int:32):
--
```
`MakeBarView` will be:
```c++
template <typename T>
auto MakeBarView(std::uint8_t x, std::int32_t y, T *data, size_t size);
```
```c++
template <typename T>
auto MakeBarView(std::uint8_t x, std::int32_t y, T *container);
```
The <code>Make*Struct*View</code> functions construct a view for *`Struct`*
over the given bytes. For the data/size form, the type `T` must be a character
type: `char`, `const char`, `unsigned char`, `const unsigned char`, `signed
char`, or `const signed char`. For the container form, the container can be a
`std::vector`, `std::array`, or `std::basic_string` of a character type, or any
other type with a `data()` method that returns a possibly-`const` `char *`,
`signed char *`, or `unsigned char *`, and a `size()` method that returns a size
in bytes. Google's `absl::string_view` is one example of such a type.
If given a pointer to a `const` character type or a `const` reference to a
container, <code>Make*Struct*View</code> will return a read-only view; otherwise
it will return a read-write view.
The result of <code>Make*Struct*View</code> should be stored in an `auto`
variable:
```c++
auto view = MakeFooView(byte_buffer, available_byte_count);
```
The specific type returned by <code>Make*Struct*View</code> is subject to
change.
### `CopyFrom` method
```c++
template <typename OtherStorage>
void CopyFrom(GenericStructView<OtherStorage> other) const;
```
The `CopyFrom` method copies data from the view `other` into the current view.
When complete, the current view's backing storage will contain the same bytes
as `other`. This works even if the view's backing storage overlaps, in which
case `other`'s backing storage is modified by the operation.
### `UncheckedCopyFrom` method
```c++
template <typename OtherStorage>
void UncheckedCopyFrom(GenericStructView<OtherStorage> other) const;
```
The `UncheckedCopyFrom` method performs the same operation as `CopyFrom` but
without any checks on the integrity of or the compatibility of the two views.
### `TryToCopyFrom` method
```c++
template <typename OtherStorage>
bool TryToCopyFrom(GenericStructView<OtherStorage> other) const;
```
`TryToCopyFrom` copies data from `other` into the current view, if `other` is
`Ok()` and the current backing storage is large enough to hold `other`'s data.
### `Equals` method
```c++
template <typename OtherStorage>
bool Equals(GenericStructView<OtherStorage> other);
```
The `Equals` method returns `true` if and only if itself and `other` contain the
same fields yielding equivalent values (as measured by the `==` operator).
`Equals()` should only be called if `Ok()` is true on both views.
### `UncheckedEquals` method
```c++
template <typename OtherStorage>
bool UncheckedEquals(GenericStructView<OtherStorage> other);
```
The `UncheckedEquals` method performs the same operation as `Equals`, but
without any checks on the integrity of or the compatibility of the two views
when reading values. `UncheckedEquals()` should only be called if `Ok()` is
true on both views.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if and only if there are enough bytes in the
backing store, and the `Ok` methods of all active fields return `true`.
### `IsComplete` method
```c++
bool IsComplete() const;
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to fully contain the `struct`. If `IsComplete()` returns `true` but
`Ok()` returns `false`, then the structure is broken in some way that cannot be
fixed by adding more bytes.
### `IntrinsicSizeInBytes` method
```c++
auto IntrinsicSizeInBytes() const;
```
or
```c++
static constexpr auto IntrinsicSizeInBytes() const;
```
The `IntrinsicSizeInBytes` method is the [field method](#struct-field-methods)
for [`$size_in_bytes`](language-reference.md#size-in-bytes). The `Read` method
of the result returns the size of the `struct`, and the `Ok` method returns
`true` if the `struct`'s intrinsic size is known; i.e.:
```c++
if (view.IntrinsicSizeInBytes().Ok()) {
// The exact return type of view.IntrinsicSizeInBytes().Read() may vary, but
// it will always be implicitly convertible to std::uint64_t.
std::uint64_t view_size = view.IntrinsicSizeInBytes().Read();
}
```
Alternately, if you are sure the size is known:
```c++
std::uint64_t view_size = view.IntrinsicSizeInBytes().UncheckedRead();
```
Or, if the size is a compile-time constant:
```c++
constexpr std::uint64_t view_size = StructView::IntrinsicSizeInBytes().Read();
constexpr std::uint64_t view_size2 = Struct::IntrinsicSizeInBytes();
```
### `MaxSizeInBytes` method
```c++
auto MaxSizeInBytes() const;
```
or
```c++
static constexpr auto MaxSizeInBytes() const;
```
The `MaxSizeInBytes` method is the [field method](#struct-field-methods)
for [`$max_size_in_bytes`](language-reference.md#max-size-in-bytes). The `Read`
method of the result returns the maximum size of the `struct`, and the `Ok`
always method returns `true`.
```c++
assert(view.MaxSizeInBytes().Ok());
// The exact return type of view.MaxSizeInBytes().Read() may vary, but it will
// always be implicitly convertible to std::uint64_t.
std::uint64_t view_size = view.MaxSizeInBytes().Read();
```
Alternately:
```c++
std::uint64_t view_size = view.MaxSizeInBytes().UncheckedRead();
```
Or:
```c++
constexpr std::uint64_t view_size = StructView::MaxSizeInBytes().Read();
constexpr std::uint64_t view_size2 = Struct::MaxSizeInBytes();
```
### `MinSizeInBytes` method
```c++
auto MinSizeInBytes() const;
```
or
```c++
static constexpr auto MinSizeInBytes() const;
```
The `MinSizeInBytes` method is the [field method](#struct-field-methods)
for [`$min_size_in_bytes`](language-reference.md#max-size-in-bytes). The `Read`
method of the result returns the minimum size of the `struct`, and the `Ok`
always method returns `true`.
```c++
assert(view.MinSizeInBytes().Ok());
// The exact return type of view.MinSizeInBytes().Read() may vary, but it will
// always be implicitly convertible to std::uint64_t.
std::uint64_t view_size = view.MinSizeInBytes().Read();
```
Alternately:
```c++
std::uint64_t view_size = view.MinSizeInBytes().UncheckedRead();
```
Or:
```c++
constexpr std::uint64_t view_size = StructView::MinSizeInBytes().Read();
constexpr std::uint64_t view_size2 = Struct::MinSizeInBytes();
```
### `SizeIsKnown` method
```c++
bool SizeIsKnown() const;
```
or
```c++
static constexpr bool SizeIsKnown() const;
```
The `SizeIsKnown` method is an alias of `IntrinsicSizeInBytes().Ok()`.
The `SizeIsKnown` method returns `true` if the size of the `struct` can be
determined from the bytes that are available. For example, consider a `struct`
like:
```
struct Message:
0 [+4] UInt payload_length (pl)
4 [+pl] UInt:8[pl] payload
```
The `Message`'s view's `SizeIsKnown` method will return `true` if at least four
bytes are available in the backing store, because it can determine the actual
size of the message if at least four bytes can be read. If the backing store
contains three or fewer bytes, then `SizeIsKnown` will be false.
Note that if the `struct` contains no dynamically-sized or dynamically-located
fields, then `SizeIsKnown` will be a `static constexpr` method that always
return `true`.
### `SizeInBytes` method
```c++
std::size_t SizeInBytes() const;
```
or
```c++
static constexpr std::size_t SizeInBytes() const;
```
The `SizeInBytes` method returns
`static_cast<std::size_t>(IntrinsicSizeInBytes().Read())`.
The `SizeInBytes` method returns the size of the `struct` in bytes.
`SizeInBytes` asserts that `SizeIsKnown()`, so applications should ensure that
`SizeIsKnown()` before calling `SizeInBytes`.
If the `struct` contains no dynamically-sized or dynamically-located fields,
then `SizeInBytes` will be a `static constexpr` method, and can always be called
safely.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the structure
from the given `stream` and update fields. Generally, applications would not
call this directly; instead, use the global `UpdateFromText` method, which
handles setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### `BackingStorage` method
```c++
Storage BackingStorage() const;
```
Returns the backing storage for the view. The return type of `BackingStorage()`
is a template parameter on the view.
### Field methods {#struct-field-methods}
Each physical field and virtual field in the `struct` will have a corresponding
method in the generated view for that `struct`, which returns a subview of that
field. For example, take the `struct` definition:
```
struct Foo:
0 [+4] UInt bar
4 [+4] Int baz
let qux = 2 * bar
let bar_alias = bar
```
In this case, the generated code will have methods
```c++
auto bar() const;
auto baz() const;
auto qux() const;
auto bar_alias() const;
```
The `bar` method will return a `UInt` view, and `baz()` will return an `Int`
view. The `qux` method will return a pseudo-`UInt` view which can only be read.
The `bar_alias` method actually forwards to `bar`, and can be both read and
written:
```c++
auto foo_view = MakeFooView(&vector_of_foo_bytes);
uint32_t bar_value = foo_view.bar().Read();
int32_t baz_value = foo_view.baz().Read();
int64_t qux_value = foo_view.qux().Read();
uint32_t bar_alias_value = foo_view.bar_alias().Read();
foo_view.bar_alias().Write(100);
assert(foo_view.bar().Read() == 100);
```
As with <code>Make*Struct*View</code>, the exact return type of field methods is
subject to change; if a field's view must be stored, use an `auto` variable.
Fields in anonymous `bits` are treated as if they were fields of the enclosing
`struct` in the generated code. Take this `struct`:
```
struct Foo:
0 [+4] bits:
5 [+5] UInt bar
```
In C++, `bar` would be read like so:
```c++
auto foo_view = MakeFooView(&vector_of_foo_bytes);
uint8_t bar_value = foo_view.bar().Read();
```
For each field, there is a <code>has_*field*()</code> method, which returns an
object. `has_` methods are typically used for conditional fields. Suppose you
have a `struct` like:
```
struct Foo:
0 [+1] enum message_type:
BAR = 1
if message_type == MessageType.BAR:
1 [+25] Bar bar
```
When you have a view of a `Foo`, you can call `foo_view.has_bar().Known()` to
find out whether `foo_view` has enough information to determine if the field
`bar` should exist. If it does `.Known()` returns `true`, you may call
`foo_view.has_bar().Value()` to find out if `bar` should exist. You can also
call `foo_view.has_bar().ValueOr(false)`, which will return `true` if `bar`'s
status is known, and `bar` exists.
Every field will have a corresponding `has_` method. In the example above,
`foo_view.has_message_type().Known()` and `foo_view.has_message_type().Value()`
are both supported calls; both will always return `true`.
Note that just because a field "exists," that does not mean that it can be read
from or written to the current message: the field's bytes might be missing, or
present but contain a non-`Ok()` value. You can use `view.field().Ok()` to
determine if the field can be *read*, and `view.field().IsComplete()` to
determine if the field can be *written*.
### Constant Virtual Fields
Virtual fields whose values are compile-time constants can be read without
instantiating a view:
```
struct Foo:
let register_number = 0xf8
0 [+4] UInt foo
```
```
// Foo::register_number() is a constexpr function.
static_assert(Foo::register_number() == 0xf8);
```
### <code>*field*().Ok()</code> vs <code>*field*().IsComplete()</code> vs <code>has_*field*()</code>
Emboss provides a number of methods to query different kinds of validity.
<code>has_*field*()</code> is used for checking the existence condition
specified in the `.emb` file:
```
struct Foo:
0 [+1] UInt x
if x < 10:
1 [+1] UInt y
```
In the .cc file:
```c++
::std::array<char, 2> bytes = { 5, 7 };
auto foo = MakeFooView(&bytes);
assert(foo.x().Read() == 5);
// foo.x() is readable, so the existence condition on y is known.
assert(foo.has_y().Known());
// foo.x().Read() < 10, so y exists in foo.
assert(foo.has_y().Value());
foo.x().Write(15);
// foo.x().Read() >= 10, so y no longer exists in foo.
assert(foo.has_y().Known());
assert(!foo.has_y().Value());
// foo.has_x() is always true, since x's existence condition is just "true".
assert(foo.has_x().Known());
assert(foo.has_x().Value());
// incomplete_foo has 0 bytes of backing storage, so x is unreadable.
auto incomplete_foo = MakeFooView(&bytes[0], 0);
// incomplete_foo.has_x() is known, since it does not depend on anything.
assert(incomplete_foo.has_x().Known());
assert(incomplete_foo.has_x().Value());
// incomplete_foo.x().Ok() is false, since x cannot be read.
assert(!incomplete_foo.x().Ok());
// Since x cannot be read, incomplete_foo.has_y().Known() is false.
assert(!incomplete_foo.has_y().Known());
// Since has_y() is not Known(), calling has_y().Value() will crash if Emboss
// assertions are enabled.
// incomplete_foo.has_y().Value() // Would crash
// It is safe to call has_y().ValueOr(false).
assert(!incomplete_foo.has_y().ValueOr(false));
```
<code>has_*field*()</code> is notional: it queries whether *`field`* *should* be
present in the view. Even if <code>has_*field*().Value()</code> is `true`,
<code>*field*().IsComplete()</code> and *field*().Ok() might return `false`.
<code>*field*().IsComplete()</code> tests if there are enough bytes in the
backing storage to hold *`field`*. If <code>*field*().IsComplete()</code>, it
is safe to call `Write()` on the field with a valid value for that field.
<code>*field*().Ok()</code> tests if there are enough bytes in the backing
storage to hold *`field`*, *and* that those bytes contain a valid value for
*`field`*:
```
struct Bar:
0 [+1] Bcd x
1 [+1] Bcd y
```
```c++
::std::array<char, 1> bytes = { 0xbb }; // Not a valid BCD number.
auto bar = MakeBarView(&bytes);
// There are enough bytes to read and write x.
assert(bar.x().IsComplete());
// The value in x is not correct.
assert(!bar.x().Ok());
// Read() would crash if assertions are enabled.
// bar.x().Read();
// Writing a valid value is safe.
bar.x().Write(99);
assert(bar.x().Ok());
// Notionally, bar should have y, even though y's byte is not available:
assert(bar.has_y().Value());
// Since there is no byte to read y from, y is not complete:
assert(!bar.y().IsComplete());
```
Note that all views have `Ok()` and `IsComplete()` methods. A view of a
structure is `Ok()` if all of its fields are either `Ok()` or not present, and
<code>has_*field*().Known()</code> is `true` for all fields.
A structure view `IsComplete()` if its `SizeIsKnown()` and its backing storage
contains at least `SizeInBits()` or `SizeInBytes()` bits or bytes. In other
words: `IsComplete()` is true if Emboss can determine that (just) adding more
bytes to the view's backing storage won't help. Note that just because
`IsComplete()` is false, that does not mean that adding more bytes *will* help.
It is possible to define incoherent structures that will confuse Emboss, such
as:
```
struct SizeNeverKnown:
if false:
0 [+1] UInt x_loc
x_loc [+1] UInt x
```
<!-- TODO(bolms): Rename "existence condition" to "presence condition." -->
## `bits` Views
The code generated for a `bits` construct is very similar to the code generated
for a `struct`. The primary differences are that there is no
<code>Make*Bits*View</code> function and that `SizeInBytes` is replaced by
`SizeInBits`.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if and only if there are enough bytes in the
backing store, and the `Ok` methods of all active fields return `true`.
### `IsComplete` method
```c++
bool IsComplete() const;
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to fully contain the `bits`. If `IsComplete()` returns `true` but
`Ok()` returns `false`, then the structure is broken in some way that cannot be
fixed by adding more bytes.
### `IntrinsicSizeInBits` method
```c++
auto IntrinsicSizeInBits() const;
```
or
```c++
static constexpr auto IntrinsicSizeInBits() const;
```
The `IntrinsicSizeInBits` method is the [field method](#bits-field-methods) for
[`$size_in_bits`](language-reference.md#size-in-bits). The `Read` method of
the result returns the size of the `struct`, and the `Ok` method returns `true`
if the `struct`'s intrinsic size is known; i.e.:
```c++
if (view.IntrinsicSizeInBits().Ok()) {
std::uint64_t view_size = view.IntrinsicSizeInBits().Read();
}
```
Since the intrinsic size of a `bits` is always a compile-time constant:
```c++
constexpr std::uint64_t view_size = BitsView::IntrinsicSizeInBits().Read();
constexpr std::uint64_t view_size2 = Bits::IntrinsicSizeInBits();
```
### `MaxSizeInBits` method
```c++
auto MaxSizeInBits() const;
```
or
```c++
static constexpr auto MaxSizeInBits() const;
```
The `MaxSizeInBits` method is the [field method](#struct-field-methods)
for [`$max_size_in_bits`](language-reference.md#max-size-in-bits). The `Read`
method of the result returns the maximum size of the `bits`, and the `Ok`
always method returns `true`.
```c++
assert(view.MaxSizeInBits().Ok());
// The exact return type of view.MaxSizeInBits().Read() may vary, but it will
// always be implicitly convertible to std::uint64_t.
std::uint64_t view_size = view.MaxSizeInBits().Read();
```
Alternately:
```c++
std::uint64_t view_size = view.MaxSizeInBits().UncheckedRead();
```
Or:
```c++
constexpr std::uint64_t view_size = StructView::MaxSizeInBits().Read();
constexpr std::uint64_t view_size2 = Struct::MaxSizeInBits();
```
### `MinSizeInBits` method
```c++
auto MinSizeInBits() const;
```
or
```c++
static constexpr auto MinSizeInBits() const;
```
The `MinSizeInBits` method is the [field method](#struct-field-methods)
for [`$min_size_in_bits`](language-reference.md#min-size-in-bits). The `Read`
method of the result returns the minimum size of the `bits`, and the `Ok`
always method returns `true`.
```c++
assert(view.MinSizeInBits().Ok());
// The exact return type of view.MinSizeInBits().Read() may vary, but it will
// always be implicitly convertible to std::uint64_t.
std::uint64_t view_size = view.MinSizeInBits().Read();
```
Alternately:
```c++
std::uint64_t view_size = view.MinSizeInBits().UncheckedRead();
```
Or:
```c++
constexpr std::uint64_t view_size = StructView::MinSizeInBits().Read();
constexpr std::uint64_t view_size2 = Struct::MinSizeInBits();
```
### `SizeIsKnown` method
```c++
static constexpr bool SizeIsKnown() const;
```
For a `bits` construct, `SizeIsKnown()` always returns `true`, because the size
of a `bits` construct is always statically known at compilation time.
### `SizeInBits` method
```c++
static constexpr std::size_t SizeInBits() const;
```
The `SizeInBits` method returns the size of the `bits` in bits. It is
equivalent to `static_cast<std::size_t>(IntrinsicSizeInBits().Read())`.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the structure
from the given `stream` and update fields. Generally, applications would not
call this directly; instead, use the global `UpdateFromText` method, which
handles setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### Field methods {#bits-field-methods}
As with `struct`, each field in a `bits` will have a corresponding method of the
same name generated, and each such method will return a view of the given field.
Take the module:
```
bits Bar:
0 [+12] UInt baz
31 [+1] Flag qux
let two_baz = baz * 2
struct Foo:
0 [+4] Bar bar
```
In this case, the generated code in the `Bar` view will have methods
```c++
auto baz() const;
auto qux() const;
auto two_baz() const;
```
The `baz` method will return a `UInt` view, and `qux()` will return a `Flag`
view:
```c++
auto foo_view = MakeFooView(&vector_of_foo_bytes);
uint16_t baz_value = foo_view.bar().baz().Read();
bool qux_value = foo_view.bar().qux().Read();
uint32_t two_baz_value = foo_view.bar().two_baz().Read();
```
The exact return type of field methods is subject to change; if a field's view
must be stored, use an `auto` variable.
## `enum`s
For each `enum` in an `.emb`, the Emboss compiler will generate a corresponding
C++11-style `enum class`. Take the following Emboss `enum`:
```
enum Foo:
BAR = 1
BAZ = 1000
```
Emboss will generate something equivalent to the following C++:
```c++
enum class Foo : uint64_t {
BAR = 1,
BAZ = 1000,
};
```
Additionally, like other Emboss entities, `enum`s have corresponding view
classes.
### `TryToGetEnumFromName` free function
```c++
static inline bool TryToGetEnumFromName(const char *name, EnumType *result);
```
The `TryToGetEnumFromName` function will try to match `name` against the names
in the Emboss `enum` definition. If it finds an exact match, it will return
`true` and update `result` with the corresponding enum value. If it does not
find a match, it will return `false` and leave `result` unchanged.
Note that `TryToGetNameFromEnum` will not match the text of the numeric value of
an enum; given the `Foo` enum above, `TryToGetEnumFromName("1000", &my_foo)`
would return `false`.
### `TryToGetNameFromEnum` free function
```c++
static inline const char *TryToGetNameFromEnum(EnumType value);
```
`TryToGetNameFromEnum` will attempt to find the textual name for the
corresponding enum value. If a name is found, it will be returned; otherwise
`TryToGetEnumFromName` will return `nullptr`. (Note that C++ enums are allowed
to contain numeric values that are not explicitly listed in the enum definition,
as long as they are in range for the underlying integral type.) If the given
value has more than one name, the first name that appears in the Emboss
definition will be returned.
### `Read` method
```c++
EnumType Read() const;
```
The `Read` method reads the enum from the underlying bytes and returns its
value as a C++ enum. `Read` will assert that there are enough bytes to read.
If the application cannot tolerate a failed assertion, it should first call
`Ok()` to ensure that it can safely read the enum. If performance is critical
and the application can assure that there will always be enough bytes to read
the enum, it can call `UncheckedRead` instead.
### `UncheckedRead` method
```c++
EnumType UncheckedRead() const;
```
Like `Read`, `UncheckedRead` reads the enum from the underlying bytes and
returns it value as a C++ enum. Unlike `Read`, `UncheckedRead` does not attempt
to validate that there are enough bytes in the backing store to actually perform
the read. In performance-critical situations, if the application is otherwise
able to ensure that there are sufficient bytes in the backing store to read the
enum, `UncheckedRead` may be used.
### `Write` method
```c++
void Write(EnumType value) const;
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the enum. If
the application cannot tolerate an assertion failure, it can use `TryToWrite` or
the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(EnumType value) const;
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not have enough bytes to hold the enum field, or `value` is
too large for the specific enum field, then `TryToWrite` will return `false` and
not update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(EnumType value);
```
`CouldWriteValue` returns `true` if the given `value` could be written into the
enum field, assuming that there were enough bytes in the backing store to cover
the field.
Although `CouldWriteValue` is `static constexpr`, it is tricky to call
statically; client code that wishes to call it statically must use `decltype`
and `declval` to get the specific type for the specific enum *field* in
question.
### `UncheckedWrite` method
```c++
void UncheckedWrite(EnumType value) const;
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
`Ok` returns `true` if there are enough bytes in the backing store for the enum
field to be read or written.
In the future, Emboss may add a "known values only" annotation to enum fields,
in which case `Ok` would also check that the given field contains a known value.
### `IsComplete` method
```c++
bool IsComplete() const;
```
`IsComplete` returns `true` if there are enough bytes in the backing store for
the enum field to be read or written.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the enum from
the given `stream` and write it into the backing store. Generally, applications
would not call this directly; instead, use the global `UpdateFromText` method,
which handles setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
## Arrays
### `operator[]` method
```c++
ElementView operator[](size_t index) const;
```
The `operator[]` method of an array view returns a view of the array element at
`index`.
### `begin()`/`rbegin()` and `end()`/`rend()` methods
```c++
ElementViewIterator<> begin();
ElementViewIterator<> end();
ElementViewIterator<> rbegin();
ElementViewIterator<> rend();
```
The `begin()` and `end()` methods of an array view returns view iterators to the
beginning and past-the-end of the array, respectively. They may be used with
arrays in range-based for loops, for example:
```c++
auto view = MakeArrayView(...);
for(auto element : view){
int a = view.member().Read();
...
}
```
The `rbegin()` and `rend()` methods of an array view returns reverse view
iterators to the end and element preceding the first, respectively.
### `SizeInBytes` or `SizeInBits` method
```c++
size_t SizeInBytes() const;
```
or
```c++
size_t SizeInBits() const;
```
Arrays in `struct`s have the `SizeInBytes` method; arrays in `bits` have the
`SizeInBits` method. `SizeInBytes` returns the size of the array in bytes;
`SizeInBits` returns the size of the array in bits.
### `ElementCount` method
```c++
size_t ElementCount() const;
```
`ElementCount` returns the number of elements in the array.
### `Ok` method
```c++
bool Ok() const;
```
`Ok` returns `true` if there are enough bytes in the backing store to hold the
entire array, and every element's `Ok` method returns `true`.
### `IsComplete` method
```c++
bool IsComplete() const;
```
`IsComplete` returns `true` if there are sufficient bytes in the backing store
to hold the entire array.
### `ToString` method
```c++
template <class String>
String ToString() const;
```
Intended usage:
```c++
// Makes a copy of view's backing storage.
auto str = view.ToString<std::string>();
// Points to view's backing storage.
auto str_view = view.ToString<std::string_view>();
```
`ToString()` returns a string type constructed from the backing storage of the
array. Note that `ToString()` is only enabled for arrays of 1-byte values,
such as `UInt:8[]`, and only when the array view's underlying storage is
contiguous.
Although it is intended for use with `std::string` and `std::string_view`,
`ToString()` can work with any C++ type that:
1. Has a `data()` method that returns a pointer to the string's underlying
data as a `char` type.
2. Has a constructor that accepts a `const declval(data())` pointer and a
`size_t` length.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the structure
from the given `stream` and update array elements. Generally, applications
would not call this directly; instead, use the global `UpdateFromText` method,
which handles setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### `BackingStorage` method
```c++
Storage BackingStorage() const;
```
Returns the backing storage for the view. The return type of `BackingStorage()`
is a template parameter on the view.
## `UInt`
### Type `ValueType`
```c++
using ValueType = ...;
```
The `ValueType` type alias maps to the least-width C++ unsigned integer type
that contains enough bits to hold any value of the given `UInt`. For example:
* a `UInt:32`'s `ValueType` would be `uint32_t`
* a `UInt:64`'s `ValueType` would be `uint64_t`
* a `UInt:12`'s `ValueType` would be `uint16_t`
* a `UInt:2`'s `ValueType` would be `uint8_t`
The `Read` and `Write` families of methods use `ValueType` to return or accept
values, respectively.
### `Read` method
```c++
ValueType Read() const;
```
The `Read` method reads the `UInt` from the underlying bytes and returns its
value as a C++ unsigned integer type. `Read` will assert that there are enough
bytes to read. If the application cannot tolerate a failed assertion, it should
first call `Ok()` to ensure that it can safely read the `UInt`. If performance
is critical and the application can assure that there will always be enough
bytes to read the `UInt`, it can call `UncheckedRead` instead.
### `UncheckedRead` method
```c++
ValueType UncheckedRead();
```
Like `Read`, `UncheckedRead` reads the `UInt` from the underlying bytes and
returns it value as a C++ unsigned integer type. Unlike `Read`, `UncheckedRead`
does not attempt to validate that there are enough bytes in the backing store to
actually perform the read. In performance-critical situations, if the
application is otherwise able to ensure that there are sufficient bytes in the
backing store to read the `UInt`, `UncheckedRead` may be used.
### `Write` method
```c++
void Write(ValueType value);
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the `UInt`. If
the application cannot tolerate an assertion failure, it can use `TryToWrite` or
the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(ValueType value);
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not have enough bytes to hold the `UInt` field, or `value` is
too large for the `UInt` field, then `TryToWrite` will return `false` and not
update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(ValueType value);
```
`CouldWriteValue` returns `true` if the given `value` could be written into the
`UInt` field, assuming that there were enough bytes in the backing store to
cover the field.
Although `CouldWriteValue` is `static constexpr`, it is tricky to call
statically; client code that wishes to call it statically must use `decltype`
and `declval` to get the specific type for the specific `UInt` field in
question.
### `UncheckedWrite` method
```c++
void UncheckedWrite(ValueType value);
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if there are enough bytes in the backing store to
hold the given `UInt` field.
### `IsComplete` method
```c++
bool IsComplete();
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to hold the given `UInt` field.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the `UInt` from
the given `stream` and update fields. Generally, applications would not call
this directly; instead, use the global `UpdateFromText` method, which handles
setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### `SizeInBits` method
```c++
static constexpr int SizeInBits();
```
The `SizeInBits` method returns the size of this specific `UInt` field, in bits.
## `Int`
### Type `ValueType`
```c++
using ValueType = ...;
```
The `ValueType` type alias maps to the least-width C++ signed integer type
that contains enough bits to hold any value of the given `Int`. For example:
* a `Int:32`'s `ValueType` would be `int32_t`
* a `Int:64`'s `ValueType` would be `int64_t`
* a `Int:12`'s `ValueType` would be `int16_t`
* a `Int:2`'s `ValueType` would be `int8_t`
The `Read` and `Write` families of methods use `ValueType` to return or accept
values, respectively.
### `Read` method
```c++
ValueType Read() const;
```
The `Read` method reads the `Int` from the underlying bytes and returns its
value as a C++ signed integer type. `Read` will assert that there are enough
bytes to read. If the application cannot tolerate a failed assertion, it should
first call `Ok()` to ensure that it can safely read the `Int`. If performance
is critical and the application can assure that there will always be enough
bytes to read the `Int`, it can call `UncheckedRead` instead.
### `UncheckedRead` method
```c++
ValueType UncheckedRead();
```
Like `Read`, `UncheckedRead` reads the `Int` from the underlying bytes and
returns it value as a C++ signed integer type. Unlike `Read`, `UncheckedRead`
does not attempt to validate that there are enough bytes in the backing store to
actually perform the read. In performance-critical situations, if the
application is otherwise able to ensure that there are sufficient bytes in the
backing store to read the `Int`, `UncheckedRead` may be used.
### `Write` method
```c++
void Write(ValueType value);
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the `Int`. If
the application cannot tolerate an assertion failure, it can use `TryToWrite` or
the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(ValueType value);
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not have enough bytes to hold the `Int` field, or `value` is
too large for the `Int` field, then `TryToWrite` will return `false` and not
update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(ValueType value);
```
`CouldWriteValue` returns `true` if the given `value` could be written into the
`Int` field, assuming that there were enough bytes in the backing store to cover
the field.
Although `CouldWriteValue` is `static constexpr`, it is tricky to call
statically; client code that wishes to call it statically must use `decltype`
and `declval` to get the specific type for the specific `Int` field in question.
### `UncheckedWrite` method
```c++
void UncheckedWrite(ValueType value);
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if there are enough bytes in the backing store to
hold the given `Int` field.
### `IsComplete` method
```c++
bool IsComplete();
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to hold the given `Int` field.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the `Int` from
the given `stream` and update fields. Generally, applications would not call
this directly; instead, use the global `UpdateFromText` method, which handles
setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### `SizeInBits` method
```c++
static constexpr int SizeInBits();
```
The `SizeInBits` method returns the size of this specific `Int` field, in bits.
## `Bcd`
### Type `ValueType`
```c++
using ValueType = ...;
```
The `ValueType` type alias maps to a C++ unsigned integer type that contains
at least enough bits to hold any value of the given `Bcd`. For example:
* a `Bcd:32`'s `ValueType` would be `uint32_t`
* a `Bcd:64`'s `ValueType` would be `uint64_t`
* a `Bcd:12`'s `ValueType` would be `uint16_t`
* a `Bcd:2`'s `ValueType` would be `uint8_t`
The `Read` and `Write` families of methods use `ValueType` to return or accept
values, respectively.
### `Read` method
```c++
ValueType Read() const;
```
The `Read` method reads the `Bcd` from the underlying bytes and returns its
value as a C++ unsigned integer type. `Read` will assert that there are enough
bytes to read, and that the binary representation is a valid BCD integer. If
the application cannot tolerate a failed assertion, it should first call `Ok()`
to ensure that it can safely read the `Bcd`. If performance is critical and the
application can assure that there will always be enough bytes to read the `Bcd`,
and that the bytes will be a valid BCD value, it can call `UncheckedRead`
instead.
### `UncheckedRead` method
```c++
ValueType UncheckedRead();
```
Like `Read`, `UncheckedRead` reads the `Bcd` from the underlying bytes and
returns it value as a C++ unsigned integer type. Unlike `Read`, `UncheckedRead`
does not attempt to validate that there are enough bytes in the backing store to
actually perform the read, nor that the bytes contain an actual BCD number. In
performance-critical situations, if the application is otherwise able to ensure
that there are sufficient bytes in the backing store to read the `Bcd`,
`UncheckedRead` may be used.
### `Write` method
```c++
void Write(ValueType value);
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the `Bcd`. If
the application cannot tolerate an assertion failure, it can use `TryToWrite` or
the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(ValueType value);
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not have enough bytes to hold the `Bcd` field, or `value` is
too large for the `Bcd` field, then `TryToWrite` will return `false` and not
update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(ValueType value);
```
`CouldWriteValue` returns `true` if the given `value` could be written into the
`Bcd` field, assuming that there were enough bytes in the backing store to cover
the field.
Although `CouldWriteValue` is `static constexpr`, it is tricky to call
statically; client code that wishes to call it statically must use `decltype`
and `declval` to get the specific type for the specific `Bcd` field in question.
### `UncheckedWrite` method
```c++
void UncheckedWrite(ValueType value);
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if there are enough bytes in the backing store to
hold the given `Bcd` field, and the bytes contain a valid BCD number: that is,
that every nibble in the backing store contains a value between 0 and 9,
inclusive.
### `IsComplete` method
```c++
bool IsComplete();
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to hold the given `Bcd` field.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the `Bcd` from
the given `stream` and update fields. Generally, applications would not call
this directly; instead, use the global `UpdateFromText` method, which handles
setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
### `SizeInBits` method
```c++
static constexpr int SizeInBits();
```
The `SizeInBits` method returns the size of this specific `Bcd` field, in bits.
## `Flag`
### `Read` method
```c++
bool Read() const;
```
The `Read` method reads the `Flag` from the underlying bit and returns its
value as a C++ `bool`. `Read` will assert that the underlying bit is in the
backing store. If the application cannot tolerate a failed assertion, it should
first call `Ok()` to ensure that it can safely read the `Flag`. If performance
is critical and the application can assure that there will always be enough
bytes to read the `Flag`, it can call `UncheckedRead` instead.
### `UncheckedRead` method
```c++
bool UncheckedRead();
```
Like `Read`, `UncheckedRead` reads the `Flag` from the underlying bit and
returns it value as a C++ bool. Unlike `Read`, `UncheckedRead` does not attempt
to validate that the backing bit is actually in the backing store. In
performance-critical situations, if the application is otherwise able to ensure
that there are sufficient bytes in the backing store to read the `Flag`,
`UncheckedRead` may be used.
### `Write` method
```c++
void Write(bool value);
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the `Flag`. If
the application cannot tolerate an assertion failure, it can use `TryToWrite` or
the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(bool value);
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not contain the `Flag`'s bit, then `TryToWrite` will return
`false` and not update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(bool value);
```
`CouldWriteValue` returns `true`, as both C++ `bool` values can be written to
any `Flag`.
### `UncheckedWrite` method
```c++
void UncheckedWrite(ValueType value);
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if the backing store contains the `Flag`'s bit.
### `IsComplete` method
```c++
bool IsComplete();
```
The `IsComplete` method returns `true` if the backing store contains the
`Flag`'s bit.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the `Flag` from
the given `stream` and update fields. Generally, applications would not call
this directly; instead, use the global `UpdateFromText` method, which handles
setting up a stream from a `std::string`.
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
## `Float`
### Type `ValueType`
```c++
using ValueType = ...;
```
The `ValueType` type alias maps to the C++ floating-point type that matches the
`Float` field's type; generally `float` for 32-bit `Float`s and `double` for
64-bit `Float`s.
The `Read` and `Write` families of methods use `ValueType` to return or accept
values, respectively.
### `Read` method
```c++
ValueType Read() const;
```
The `Read` method reads the `Float` from the underlying bytes and returns its
value as a C++ floating point type. `Read` will assert that there are enough
bytes to read. If the application cannot tolerate a failed assertion, it should
first call `Ok()` to ensure that it can safely read the `Float`. If performance
is critical and the application can assure that there will always be enough
bytes to read the `Float`, it can call `UncheckedRead` instead.
### `UncheckedRead` method
```c++
ValueType UncheckedRead();
```
Like `Read`, `UncheckedRead` reads the `Float` from the underlying bytes and
returns it value as a C++ floating point type. Unlike `Read`, `UncheckedRead`
does not attempt to validate that there are enough bytes in the backing store to
actually perform the read. In performance-critical situations, if the
application is otherwise able to ensure that there are sufficient bytes in the
backing store to read the `Float`, `UncheckedRead` may be used.
### `Write` method
```c++
void Write(ValueType value);
```
`Write` writes the `value` into the backing store. Like `Read`, `Write` asserts
that there are enough bytes in the backing store to safely write the `Float`.
If the application cannot tolerate an assertion failure, it can use `TryToWrite`
or the combination of `IsComplete` and `CouldWriteValue`.
### `TryToWrite` method
```c++
bool TryToWrite(ValueType value);
```
`TryToWrite` attempts to write the `value` into the backing store. If the
backing store does not have enough bytes to hold the `Float` field, then
`TryToWrite` will return `false` and not update anything.
### `CouldWriteValue` method
```c++
static constexpr bool CouldWriteValue(ValueType value);
```
`CouldWriteValue` returns `true`.
### `UncheckedWrite` method
```c++
void UncheckedWrite(ValueType value);
```
Like `Write`, `UncheckedWrite` writes the given value to the backing store.
Unlike `Write`, `UncheckedWrite` does not check that there are actually enough
bytes in the backing store to safely write; it should only be used if the
application has ensured that there are sufficient bytes in the backing store in
some other way, and performance is a concern.
### `Ok` method
```c++
bool Ok() const;
```
The `Ok` method returns `true` if there are enough bytes in the backing store to
hold the given `Float` field.
### `IsComplete` method
```c++
bool IsComplete();
```
The `IsComplete` method returns `true` if there are enough bytes in the backing
store to hold the given `Float` field.
### `UpdateFromTextStream` method
```c++
template <class Stream>
bool UpdateFromTextStream(Stream *stream) const;
```
`UpdateFromTextStream` will read a text-format representation of the `Float`
from the given `stream` and update fields. Generally, applications would not
call this directly; instead, use the global `UpdateFromText` method, which
handles setting up a stream from a `std::string`.
*Note: this method is not yet implemented.*
### `WriteToTextStream` method
```c++
template <class Stream>
bool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
```
`WriteToTextStream` will write a text representation of the current value in a
form that can be decoded by `UpdateFromTextStream`. Generally, applications
would not call this directly; instead, use the global `WriteToString` method,
which handles setting up the stream and returning the resulting string.
*Note: this method is not yet implemented.*
## `::emboss::UpdateFromText` function
```c++
template <typename EmbossViewType>
bool UpdateFromText(EmbossViewType view, const ::std::string &text) const;
```
The `::emboss::UpdateFromText` function constructs an appropriate text strem
object from the given `text` and calls `view`'s `UpdateFromTextStream` method.
This is the preferred way to read Emboss text format in C++.
## `::emboss::WriteToString` function
```c++
template <typename EmbossViewType>
::std::string WriteToString(EmbossViewType view);
template <typename EmbossViewType>
::std::string WriteToString(EmbossViewType view, TextOutputOptions options);
```
The `::emboss::WriteToString` function constructs a string stream, passes it
into the `view`'s `WriteToTextStream` method, and finally returns the text
format of the `view`.
The single-argument form `WriteToString(view)` will return a single line of
text. For more readable output, `WriteToString(view, ::emboss::MultilineText())`
should help.
## `::emboss::TextOutputOptions` class
The `TextOutputOptions` is used to set options for text output, such as numeric
base, whether or not to use multiple lines, etc.
### `PlusOneIndent` method
```c++
TextOutputOptions PlusOneIndent() const;
```
`PlusOneIndent` returns a new `TextOutputOptions` with one more level of
indentation than the current `TextOutputOptions`. This is primarily intended for
use inside of `WriteToTextStream` methods, as a way to get an indented
`TextOutputOptions` to pass to the `WriteToTextStream` methods of child
objects. However, application callers may use `PlusOneIndent()`, possibly
multiple times, to indent the entire output.
### `Multiline` method
```c++
TextOutputOptions Multiline(bool new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `multiline()`.
### `WithIndent` method
```c++
TextOutputOptions WithIndent(::std::string new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `indent()`.
### `WithComments` method
```c++
TextOutputOptions WithComments(bool new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `comments()`.
### `WithDigitGrouping` method
```c++
TextOutputOptions WithDigitGrouping(bool new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `digit_grouping()`.
### `WithNumericBase` method
```c++
TextOutputOptions WithNumericBase(int new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `digit_grouping()`. The new
numeric base should be 2, 10, or 16.
### `WithAllowPartialOutput` method
```c++
TextOutputOptions WithAllowPartialOutput(bool new_value) const;
```
Returns a new `TextOutputOptions` with the same options as the current
`TextOutputOptions`, except for a new value for `allow_partial_output()`.
### `current_indent` method
```c++
::std::string current_indent() const; // Default "".
```
Returns the current indent string.
### `indent` method
```c++
::std::string indent() const; // Default " ".
```
Returns the indent string. The indent string is the string used for a *single*
level of indentation.
### `multiline` method
```c++
bool multiline() const; // Default false.
```
Returns `true` if text output should use multiple lines, or `false` if text
output should be single-line only.
### `digit_grouping` method
```c++
bool digit_grouping() const; // Default false.
```
Returns `true` if text output should include digit separators on numbers; i.e.
`1_000_000` instead of `1000000`.
### `comments` method
```c++
bool comments() const; // Default false.
```
Returns `true` if text output should include comments, e.g., to show numbers in
multiple bases.
### `numeric_base` method
```c++
uint8_t numeric_base() const; // Default 10.
```
Returns the numeric base that should be used for formatting numbers. This should
always be 2, 10, or 16.
### `allow_partial_output` method
```c++
bool allow_partial_output() const; // Default false.
```
Returns `true` if text output should attempt to extract fields from a view that
is not `Ok()`. If so:
* `WriteToString()` or `WriteToTextStream()` should never `CHECK`-fail.
* Atomic fields (e.g., `Int`, `UInt`, `enum`, `Flag`, etc. types) will not be
written to the text stream if they cannot be read.
* If `comments()` is also `true`, unreadable atomic fields will be commented
in the text stream.
* Aggregate fields (`struct`, `bits`, or arrays) will be written, but may be
missing fields or entirely empty if they have non-`Ok()` members.