Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
109
third-party/vendor/arrayref/README.md
vendored
Normal file
109
third-party/vendor/arrayref/README.md
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# arrayref
|
||||
|
||||
[](https://travis-ci.org/droundy/arrayref)
|
||||
[](https://coveralls.io/github/droundy/arrayref?branch=master)
|
||||
|
||||
[Documentation](https://docs.rs/arrayref)
|
||||
|
||||
This is a very small rust module, which contains just four macros, for
|
||||
the taking of array references to slices of... sliceable things.
|
||||
These macros (which are awkwardly named) should be perfectly safe, and
|
||||
have seen just a tad of code review.
|
||||
|
||||
## Why would I want this?
|
||||
|
||||
The goal of arrayref is to enable the effective use of APIs that
|
||||
involve array references rather than slices, for situations where
|
||||
parameters must have a given size. As an example, consider the
|
||||
`byteorder` crate. This is a very nice crate with a simple API
|
||||
containing functions that look like:
|
||||
|
||||
```rust
|
||||
fn read_u16(buf: &[u8]) -> u16;
|
||||
fn write_u16(buf: &mut [u8], n: u16);
|
||||
```
|
||||
|
||||
Looking at this, you might wonder why they accept a slice reference as
|
||||
input. After all, they always want just two bytes. These functions
|
||||
must panic if given a slice that is too small, which means that unless
|
||||
they are inlined, then a runtime bounds-check is forced, even if it
|
||||
may be statically known that the input is the right size.
|
||||
|
||||
Wouldn't it be nicer if we had functions more like
|
||||
|
||||
```rust
|
||||
fn read_u16_array(buf: &[u8; 2]) -> u16;
|
||||
fn write_u16_array(buf: &mut [u8; 2], n: u16);
|
||||
```
|
||||
|
||||
The type signature would tell users precisely what size of input is
|
||||
required, and the compiler could check at compile time that the input
|
||||
is of the appropriate size: this sounds like the zero-cost
|
||||
abstractions rust is famous for! However, there is a catch, which
|
||||
arises when you try to *use* these nicer functions, which is that
|
||||
usually you are looking at two bytes in a stream. So, e.g. consider
|
||||
that we are working with a hypothetical (and simplified) ipv6 address.
|
||||
|
||||
Doing this with our array version (which looks so beautiful in terms
|
||||
of accurately describing what we want!) looks terrible:
|
||||
|
||||
```rust
|
||||
let addr: &[u8; 16] = ...;
|
||||
let mut segments = [0u16; 8];
|
||||
// array-based API
|
||||
for i in 0 .. 8 {
|
||||
let mut two_bytes = [addr[2*i], addr[2*i+1]];
|
||||
segments[i] = read_u16_array(&two_bytes);
|
||||
}
|
||||
// slice-based API
|
||||
for i in 0 .. 8 {
|
||||
segments[i] = read_u16(&addr[2*i..]);
|
||||
}
|
||||
```
|
||||
|
||||
The array-based approach looks way worse. We need to create a fresh
|
||||
copy of the bytes, just so it will be in an array of the proper size!
|
||||
Thus the whole "zero-cost abstraction" argument for using array
|
||||
references fails. The trouble is that there is no (safe) way (until
|
||||
[RFC 495][1] lands) to obtain an array reference to a portion of a
|
||||
larger array or slice. Doing so is the equivalent of taking a slice
|
||||
with a size known at compile time, and ought to be built into the
|
||||
language.
|
||||
|
||||
[1]: https://github.com/rust-lang/rfcs/blob/master/text/0495-array-pattern-changes.md
|
||||
|
||||
The arrayref crate allows you to do this kind of slicing. So the
|
||||
above (very contrived) example can be implemented with array
|
||||
references as:
|
||||
|
||||
```rust
|
||||
let addr: &[u8; 16] = ...;
|
||||
let mut segments = [0u16; 8];
|
||||
// array-based API with arrayref
|
||||
for i in 0 .. 8 {
|
||||
segments[i] = read_u16_array(array_ref![addr,2*i,2]);
|
||||
}
|
||||
```
|
||||
|
||||
Here the `array_ref![addr,2*i,2]` macro allows us to take an array
|
||||
reference to a slice consisting of two bytes starting at `2*i`. Apart
|
||||
from the syntax (less nice than slicing), it is essentially the same
|
||||
as the slice approach. However, this code makes explicit the
|
||||
need for precisely *two* bytes both in the caller, and in the function
|
||||
signature.
|
||||
|
||||
This module provides three other macros providing related
|
||||
functionality, which you can read about in the
|
||||
[documentation](https://droundy.github.io/arrayref).
|
||||
|
||||
For an example of how these macros can be used in an actual program,
|
||||
see [my rust translation of tweetnacl][2], which uses `arrayref`
|
||||
to almost exclusively accept array references in functions, with the
|
||||
only exception being those which truly expect data of arbitrary
|
||||
length. In my opinion, the result is code that is far more legible
|
||||
than the original C code, since the size of each argument is
|
||||
explicit. Moreover (although I have not tested this), the use of
|
||||
array references rather than slices *should* result in far fewer
|
||||
bounds checks, since almost all sizes are known at compile time.
|
||||
|
||||
[2]: https://github.com/droundy/onionsalt/blob/master/src/crypto.rs
|
||||
Loading…
Add table
Add a link
Reference in a new issue