Perform out-of-bounds check in `Binary_string.Reader.read`

When performing a single out-of-bounds check in
`Binary_string.Reader.read`, we can guarantee to code using `read` it
can use unsafe functions to access the string returned by it, as long
as it only accesses the substring from the given offset, and the offset
plus the requested length.
Use unsafe functions

Since we no longer need to perform out-of-bounds checks in actual
parsing code (42b612f82e), 'unsafe' accessors can be used.

This commit alters the `char` parser to use `String.unsafe_get`,
the 'unsafe' modules of 'ocplib-endian', and a custom substring
extraction function.

The latter was validated using a benchmark included in this commit,
which shows a 35% improvement on my machine.

See: 42b612f82e94868ff6a7f8bce0d07e7ae069f41c
Add benchmark comparing applicative & monadic interfaces