## Bytevectors

Bytevectors represent blocks of binary data. They are fixed-length sequences of bytes, where a `byte` is an exact integer in the range [0, 255]. A bytevector is typically more space-efficient than a vector containing the same values.

The length of a bytevector is the number of elements that it contains. This number is a non-negative integer that is fixed when the bytevector is created. The valid indexes of a bytevector are the exact non-negative integers less than the length of the bytevector, starting at index zero as with vectors.

The `bytevector` type is equivalent to the `u8vector` uniform vector type, but is specified by the R7RS standard.

Bytevectors are written using the notation `#u8(byte . . . )`. For example, a bytevector of length 3 containing the byte 0 in element 0, the byte 10 in element 1, and the byte 5 in element 2 can be written as following:

```#u8(0 10 5)
```

Bytevector constants are self-evaluating, so they do not need to be quoted in programs.

Type: `bytevector`

The type of bytevector objects.

Constructor: `bytevector` `byte` `…`

Return a newly allocated bytevector whose elements contain the given arguments. Analogous to `vector`.

```(bytevector 1 3 5 1 3 5)  ⇒  #u8(1 3 5 1 3 5)
(bytevector)  ⇒  #u8()
```

Procedure: `bytevector?` `obj`

Return `#t` if `obj` is a bytevector, `#f` otherwise.

Procedure: `make-bytevector` `k`

Procedure: `make-bytevector` `k` `byte`

The `make-bytevector` procedure returns a newly allocated bytevector of length `k`. If `byte` is given, then all elements of the bytevector are initialized to `byte`, otherwise the contents of each element are unspecified.

```(make-bytevector 2 12) ⇒ #u8(12 12)
```

Procedure: `bytevector-length` `bytevector`

Returns the length of `bytevector` in bytes as an exact integer.

Procedure: `bytevector-u8-ref` `bytevector` `k`

It is an error if `k` is not a valid index of `bytevector`. Returns the `k`th byte of `bytevector`.

```(bytevector-u8-ref ’#u8(1 1 2 3 5 8 13 21) 5)
⇒ 8
```

Procedure: `bytevector-u8-set!` `bytevector` `k` `byte`

It is an error if `k` is not a valid index of `bytevector`. Stores `byte` as the `k`th byte of `bytevector`.

```(let ((bv (bytevector 1 2 3 4)
(bytevector-u8-set! bv 1 3)
bv)
⇒ #u8(1 3 3 4)
```

Procedure: `bytevector-copy` `bytevector` [`start` [`end`]]

Returns a newly allocated bytevector containing the bytes in `bytevector` between `start` and `end`.

```(define a #u8(1 2 3 4 5))
(bytevector-copy a 2 4))
⇒ #u8(3 4)
```

Procedure: `bytevector-copy!` `to` `at` `from` [`start` [`end`]]

Copies the bytes of bytevector`from` between `start` and `end` to bytevector `to`, starting at `at`. The order in which bytes are copied is unspecified, except that if the source and destination overlap, copying takes place as if the source is first copied into a temporary bytevector and then into the destination. This is achieved without allocating storage by making sure to copy in the correct direction in such circumstances.

It is an error if `at` is less than zero or greater than the length of `to`. It is also an error if `(- (bytevector-length to) at)` is less than `(- end start)`.

```(define a (bytevector 1 2 3 4 5))
(define b (bytevector 10 20 30 40 50))
(bytevector-copy! b 1 a 0 2)
b        ⇒ #u8(10 1 2 40 50)
```

Procedure: `bytevector-append` `bytevector...`

Returns a newly allocated bytevector whose elements are the concatenation of the elements in the given bytevectors.

```(bytevector-append #u8(0 1 2) #u8(3 4 5))
⇒  #u8(0 1 2 3 4 5)
```

### Converting to or from strings

Procedure: `utf8->string` `bytevector` [`start` [`end`]]

This procedure decodes the bytes of a bytevector between `start` and `end`, interpreting as a UTF-8-encoded string, and returns the corresponding string. It is an error for `bytevector` to contain invalid UTF-8 byte sequences.

```(utf8->string #u8(#x41))  ⇒ "A"
```

Procedure: `utf16->string` `bytevector` [`start` [`end`]]

Procedure: `utf16be->string` `bytevector` [`start` [`end`]]

Procedure: `utf16le->string` `bytevector` [`start` [`end`]]

These procedures interpret their <var>bytevector</var> argument as a UTF-16 encoding of a sequence of characters, and return an istring containing that sequence.

The bytevector subrange given to `utf16->string` may begin with a byte order mark (BOM); if so, that BOM determines whether the rest of the subrange is to be interpreted as big-endian or little-endian; in either case, the BOM will not become a character in the returned string. If the subrange does not begin with a BOM, it is decoded using the same implementation-dependent endianness used by `string->utf16`.

The `utf16be->string` and `utf16le->string` procedures interpret their inputs as big-endian or little-endian, respectively. If a BOM is present, it is treated as a normal character and will become part of the result.

It is an error if `(- end start)` is odd, or if the bytevector subrange contains invalid UTF-16 byte sequences.

Procedure: `string->utf8` `string` [`start` [`end`]]

This procedure encodes the characters of a string between `start` and `end` and returns the corresponding bytevector, in UTF-8 encoding.

```(string->utf8 "λ")     ⇒ " #u8(#xCE #xBB)
```

Procedure: `string->utf16` `string` [`start` [`end`]]

Procedure: `string->utf16be` `string` [`start` [`end`]]

Procedure: `string->utf16le` `string` [`start` [`end`]]

These procedures return a newly allocated (unless empty) bytevector containing a UTF-16 encoding of the given substring.

The bytevectors returned by `string->utf16be` and `string->utf16le` do not contain a byte-order mark (BOM); `string->utf16be`> returns a big-endian encoding, while `string->utf16le` returns a little-endian encoding.

The bytevectors returned by `string->utf16` begin with a BOM that declares an implementation-dependent endianness, and the bytevector elements following that BOM encode the given substring using that endianness.

Rationale: These procedures are consistent with the Unicode standard. Unicode suggests UTF-16 should default to big-endian, but Microsoft prefers little-endian.