template <typename Storage>

struct StorageTraits

Defined at line 82 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

The zbitl::StorageTraits template must be specialized for each type used as

the Storage type parameter to zbitl::View (see

<lib

/zbitl/view.h). The

generic template can only be instantiated with `std::tuple

<

>` as the

Storage type. This is a stub implementation that always fails with an

empty error_type. It also serves to document the API for StorageTraits

specializations.

The underlying storage memory is expected to be

`kStorageAlignment`-aligned.

Public Methods

std::string_view error_string (error_type error)

This method is expected to return a type convertible to std::string_view

(e.g., std::string or const char*) representing the message associated to

a given error value. The returned object is "owning" and so it is

expected that the caller keep the returned object alive for as long as

they use any string_view converted from it.

Defined at line 101 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type, uint32_t> Capacity (Storage & zbi)

This returns the upper bound on available space where the ZBI is stored.

The container must fit within this maximum. Storage past the container's

self-encoded size need not be accessible and will never be accessed.

If the actual upper bound is unknown, this can safely return UINT32_MAX.

Defined at line 107 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> EnsureCapacity (Storage & zbi, uint32_t capacity)

A specialization must define this if it also defines Write. This method

ensures that the capacity is at least that of the provided value

(possibly larger), for specializations where such an operation is

sensible.

Defined at line 115 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type, payload_type> Payload (Storage & zbi, uint32_t offset, uint32_t length)

This fetches the item payload view object, whatever that means for this

Storage type. This is not expected to read the contents, just transfer a

pointer or offset around so they can be explicitly read later.

Defined at line 122 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <typename Callback>
fit::result<error_type, decltype(callback(ByteView{}))> Read (Storage & zbi, payload_type payload, uint32_t length, Callback && callback)

Referred to as the "buffered read".

This reads the payload indicated by a payload_type as returned by Payload

and feeds it to the callback in chunks sized for the convenience of the

storage backend. The length is guaranteed to match that passed to

Payload to fetch this payload_type value.

The callback returns some type fit::result

<E

>. Read returns

fit::result

<error

_type, fit::result

<E

>>>, yielding a storage error or

the result of the callback. If a callback returns an error, its return

value is used immediately. If a callback returns success, another

callback may be made for another chunk of the payload. If the payload is

empty (`length` == 0), there will always be a single callback made with

an empty data argument.

Defined at line 142 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> Read (Storage & zbi, payload_type payload, void * buffer, uint32_t length)

Referred to as the "unbuffered read".

A specialization provides this overload if the payload can be read

directly into a provided buffer for zero-copy operation.

Defined at line 151 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <PayloadCompatibleStorage T, bool LowLocality>
fit::result<error_type, std::span<const T>> Read (Storage & zbi, payload_type payload, uint32_t length)

Referred to as the "one-shot read".

A specialization only provides this overload if the payload can be

accessed directly in memory. If this overload is provided, then the other

overloads need not be provided. The returned view is only guaranteed

valid until the next use of the same Storage object. So it could

e.g. point into a cache that's repurposed by this or other calls made

later using the same object.

One may attempt to read the data out in any particular form, parameterized

by `T`, provided that `alignof(T)

<

= kStorageAlignment`. The offset

associated with `payload` is expected to be `alignof(T)`-aligned, though

that is an invariant that the caller must keep track of.

`LowLocality` gives whether there is an expectation that adjacent data

will subsequently be read; if true, the amortized cost of the read might

be determined to be too high and storage backends might decide to perform

the read differently or not implement the method at all in this case.

Defined at line 175 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <PayloadCompatibleStorage T, bool LowLocality>
fit::result<error_type, std::span<const T>> Read (Storage & zbi, payload_type payload, uint32_t length)

Referred to as the "one-shot read".

A specialization only provides this overload if the payload can be

accessed directly in memory. If this overload is provided, then the other

overloads need not be provided. The returned view is only guaranteed

valid until the next use of the same Storage object. So it could

e.g. point into a cache that's repurposed by this or other calls made

later using the same object.

One may attempt to read the data out in any particular form, parameterized

by `T`, provided that `alignof(T)

<

= kStorageAlignment`. The offset

associated with `payload` is expected to be `alignof(T)`-aligned, though

that is an invariant that the caller must keep track of.

`LowLocality` gives whether there is an expectation that adjacent data

will subsequently be read; if true, the amortized cost of the read might

be determined to be too high and storage backends might decide to perform

the read differently or not implement the method at all in this case.

Defined at line 175 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <PayloadCompatibleStorage T, bool LowLocality>
fit::result<error_type, std::span<const T>> Read (Storage & zbi, payload_type payload, uint32_t length)

Referred to as the "one-shot read".

A specialization only provides this overload if the payload can be

accessed directly in memory. If this overload is provided, then the other

overloads need not be provided. The returned view is only guaranteed

valid until the next use of the same Storage object. So it could

e.g. point into a cache that's repurposed by this or other calls made

later using the same object.

One may attempt to read the data out in any particular form, parameterized

by `T`, provided that `alignof(T)

<

= kStorageAlignment`. The offset

associated with `payload` is expected to be `alignof(T)`-aligned, though

that is an invariant that the caller must keep track of.

`LowLocality` gives whether there is an expectation that adjacent data

will subsequently be read; if true, the amortized cost of the read might

be determined to be too high and storage backends might decide to perform

the read differently or not implement the method at all in this case.

Defined at line 175 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <PayloadCompatibleStorage T, bool LowLocality>
fit::result<error_type, std::span<const T>> Read (Storage & zbi, payload_type payload, uint32_t length)

Referred to as the "one-shot read".

A specialization only provides this overload if the payload can be

accessed directly in memory. If this overload is provided, then the other

overloads need not be provided. The returned view is only guaranteed

valid until the next use of the same Storage object. So it could

e.g. point into a cache that's repurposed by this or other calls made

later using the same object.

One may attempt to read the data out in any particular form, parameterized

by `T`, provided that `alignof(T)

<

= kStorageAlignment`. The offset

associated with `payload` is expected to be `alignof(T)`-aligned, though

that is an invariant that the caller must keep track of.

`LowLocality` gives whether there is an expectation that adjacent data

will subsequently be read; if true, the amortized cost of the read might

be determined to be too high and storage backends might decide to perform

the read differently or not implement the method at all in this case.

Defined at line 175 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> Write (Storage & zbi, uint32_t offset, ByteView data)

Referred to as the "buffered write".

A specialization defines this only if it supports mutation. It might be

called to write whole or partial headers and/or payloads, but it will

never be called with an offset and size that would exceed the capacity

previously reported by Capacity (above). It returns success only if it

wrote the whole chunk specified. If it returns an error, any subset of

the chunk that failed to write might be corrupted in the image and the

container will always revalidate everything.

Defined at line 189 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> Write (Storage & zbi, uint32_t offset, ByteView data)

Referred to as the "buffered write".

A specialization defines this only if it supports mutation. It might be

called to write whole or partial headers and/or payloads, but it will

never be called with an offset and size that would exceed the capacity

previously reported by Capacity (above). It returns success only if it

wrote the whole chunk specified. If it returns an error, any subset of

the chunk that failed to write might be corrupted in the image and the

container will always revalidate everything.

Defined at line 189 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> Write (Storage & zbi, uint32_t offset, ByteView data)

Referred to as the "buffered write".

A specialization defines this only if it supports mutation. It might be

called to write whole or partial headers and/or payloads, but it will

never be called with an offset and size that would exceed the capacity

previously reported by Capacity (above). It returns success only if it

wrote the whole chunk specified. If it returns an error, any subset of

the chunk that failed to write might be corrupted in the image and the

container will always revalidate everything.

Defined at line 189 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type> Write (Storage & zbi, uint32_t offset, ByteView data)

Referred to as the "buffered write".

A specialization defines this only if it supports mutation. It might be

called to write whole or partial headers and/or payloads, but it will

never be called with an offset and size that would exceed the capacity

previously reported by Capacity (above). It returns success only if it

wrote the whole chunk specified. If it returns an error, any subset of

the chunk that failed to write might be corrupted in the image and the

container will always revalidate everything.

Defined at line 189 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type, void *> Write (Storage & zbi, uint32_t offset, uint32_t length)

Referred to as the "unbuffered write".

A specialization may define this if it also defines Write. It returns a

pointer where the data can be mutated directly in memory. That pointer is

only guaranteed valid until the next use of the same Storage object. So

it could e.g. point into a cache that's repurposed by this or other calls

made later using the same object.

Defined at line 200 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

fit::result<error_type, Storage> Create (Storage & zbi, uint32_t capacity, uint32_t initial_zero_size)

A specialization defines this only if it supports mutation and if creating

new storage from whole cloth makes sense for the storage type somehow.

Its successful return value is whatever makes sense for returning a new,

owning object of a type akin to Storage (possibly Storage itself, possibly

another type). The new object refers to new storage of at least the given

capacity (in bytes) with a provided zero-fill header size. The old

storage object might be used as a prototype in some sense, but the new

object is distinct storage.

Defined at line 212 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <typename SlopCheck>
fit::result<error_type, std::optional<std::pair<Storage, uint32_t>>> Clone (Storage & zbi, uint32_t offset, uint32_t length, uint32_t to_offset, SlopCheck && slopcheck)

A specialization defines this only if it defines Create, and if Clone adds

any value. The new object is new storage that doesn't mutate the original

storage, whose capacity is at least `to_offset + length`, and whose

contents are the subrange of the original storage starting at `offset`,

with zero-fill from the beginning of the storage up to `to_offset` bytes.

The successful return value is `std::optional

<std

::pair

<T

, uint32_t>>`

where T is what a successful Create call returns and the uint32_t is the

actual offset into the new storage, aka the "slop" (see below). If this

doesn't have something more efficient to do than just allocating storage

space for and copying all `length` bytes of data (using Create and Write),

then it can just return std::nullopt. If the method would *always* return

std::nullopt then it can just be omitted entirely. The "slop" refers to

some number of bytes at the beginning of the storage that will read as

zero before the requested range of the original storage begins. The

storage backend will endeavor to make this match `to_offset`, but might

deliver a different result due to factors like page-rounding. The

`slopcheck` parameter is a `(uint32_t) -> bool` predicate function object

that says whether a given byte count is acceptable as slop for this clone.

If `slopcheck(slop)` returns false, Clone *must* return std::nullopt

rather than yielding storage with a rejected slop byte count.

Defined at line 238 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

template <typename SlopCheck>
fit::result<error_type, std::optional<std::pair<Storage, uint32_t>>> Clone (Storage & zbi, uint32_t offset, uint32_t length, uint32_t to_offset, SlopCheck && slopcheck)

A specialization defines this only if it defines Create, and if Clone adds

any value. The new object is new storage that doesn't mutate the original

storage, whose capacity is at least `to_offset + length`, and whose

contents are the subrange of the original storage starting at `offset`,

with zero-fill from the beginning of the storage up to `to_offset` bytes.

The successful return value is `std::optional

<std

::pair

<T

, uint32_t>>`

where T is what a successful Create call returns and the uint32_t is the

actual offset into the new storage, aka the "slop" (see below). If this

doesn't have something more efficient to do than just allocating storage

space for and copying all `length` bytes of data (using Create and Write),

then it can just return std::nullopt. If the method would *always* return

std::nullopt then it can just be omitted entirely. The "slop" refers to

some number of bytes at the beginning of the storage that will read as

zero before the requested range of the original storage begins. The

storage backend will endeavor to make this match `to_offset`, but might

deliver a different result due to factors like page-rounding. The

`slopcheck` parameter is a `(uint32_t) -> bool` predicate function object

that says whether a given byte count is acceptable as slop for this clone.

If `slopcheck(slop)` returns false, Clone *must* return std::nullopt

rather than yielding storage with a rejected slop byte count.

Defined at line 238 of file ../../src/lib/zbitl/include/lib/zbitl/storage-traits.h

Records