https://bugzilla.mozilla.org/show_bug.cgi?id=1295611 has landed and
added mozilla::Span (#include "mozilla/Span.h"; code in mfbt/Span.h). Going
forward, please consider using mozilla::Span
as a method argument where you'd previously have used a pointer argument
and a length argument.

Span implements Rust's slice concept for C++. It's called "Span" instead of
"Slice" to follow the naming used in C++ Core Guidelines.

A Span wraps a pointer and a length that identify a non-owning view to a
contiguous block of memory of objects of the same type. Various types,
including (pre-decay) C arrays, XPCOM strings, nsTArray, mozilla::Array,
mozilla::Range and contiguous standard-library containers, auto-convert
into Spans when attempting to pass them as arguments to methods that take
Spans. MakeSpan() functions can be used for explicit conversion in other
contexts. MakeSpan() works conveniently with local variables declared
as auto, so you don't need to write the type parameter of the Span.
(Span itself autoconverts into mozilla::Range.)

Like Rust's slices, Span provides safety against out-of-bounds access by
performing run-time bound checks. However, unlike Rust's slices, Span
cannot provide safety against use-after-free.

(Note: Span is like Rust's slice only conceptually. Due to the lack of
ABI guarantees, you should still decompose spans/slices to raw pointer
and length parts when crossing the FFI.)

In addition to having constructors and MakeSpan() functions that take
various well-known types, a Span for an arbitrary type can be constructed
(via constructor or MakeSpan()) from a pointer and a length or a pointer
and another pointer pointing just past the last element.

A Span<const char> can be obtained for const char* pointing to a
zero-terminated C string using the MakeCStringSpan() function. A
corresponding implicit constructor does not exist in order to avoid
accidental construction in cases where const char* does not point to a
zero-terminated C string.

Span has methods that follow the Mozilla naming style and methods that
don't. The methods that follow the Mozilla naming style are meant to be
used directly from Mozilla code. The methods that don't are meant for
integration with C++11 range-based loops and with meta-programming that
expects the same methods that are found on the standard-library
containers. For example, to decompose a Span into its parts in Mozilla
code, use Elements() and Length() (as with nsTArray) instead of data()
and size() (as with std::vector).

The pointer and length wrapped by a Span cannot be changed after a Span has
been created. When new values are required, simply create a new Span. Span
has a method called Subspan() that works analogously to the Substring()
method of XPCOM strings taking a start index and an optional length. As a
Mozilla extension (relative to Microsoft's gsl::span that mozilla::Span is
based on), Span has methods From(start), To(end) and FromTo(start, end)
that correspond to Rust's &slice[start..], &slice[..end] and
&slice[start..end], respectively. (That is, the end index is the index of
the first element not to be included in the new subspan.)

When indicating a Span that's only read from, const goes inside the type
parameter. Don't put const in front of Span. That is:
size_t ReadsFromOneSpanAndWritesToAnother(Span<const uint8_t> aReadFrom,
Span<uint8_t> aWrittenTo);

Any Span<const T> can be viewed as Span<const uint8_t> using the function
AsBytes(). Any Span<T> can be viewed as Span<uint8_t> using the function
AsWritableBytes().

FAQ: Why introduce mozilla::Span when mozilla::Range already exits?

1) Span's storage (pointer and length as opposed to pointer and
pointer) matches Rust's slices without arithmetic, so they
decompose and recompose as the other on the other side of
the FFI without arithmetic.

2) An earlier dev-platform thread seemed to OK Span on the
grounds of it having enough of a pedigree from C++ Core
Guidelines.

-- 
Henri Sivonen
hsivo...@hsivonen.fi
https://hsivonen.fi/
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to