|
2 | 2 |
|
3 | 3 | #![no_std]
|
4 | 4 |
|
5 |
| -#[deny(missing_docs, unsafe_code)] |
| 5 | +#[deny(missing_docs)] |
6 | 6 | #[cfg_attr(feature = "cargo-clippy", deny(clippy))]
|
7 | 7 |
|
8 | 8 | /// Possible errors returned by the API.
|
9 | 9 | #[derive(Debug, Copy, Clone)]
|
10 | 10 | pub enum Error {
|
11 |
| - /// Input contains an invalid character. |
12 |
| - InvalidData, |
13 |
| - /// Input contained the start of a multi-byte character but its tail was missing. |
14 |
| - BufferUnderflow, |
15 |
10000
11 | /// Not enough space left in the output buffer.
|
16 | 12 | BufferOverflow,
|
17 | 13 | /// Input contained a character which cannot be represented in UCS-2.
|
@@ -60,29 +56,25 @@ where
|
60 | 56 | i += 1;
|
61 | 57 | } else if bytes[i] & 0b1110_0000 == 0b1100_0000 {
|
62 | 58 | // 2 byte codepoint
|
63 |
| - if i + 1 == len { |
64 |
| - // Buffer underflow |
65 |
| - return Err(Error::BufferUnderflow); |
66 |
| - } |
67 |
| - if bytes[i + 1] & 0b1100_0000 != 0b1000_0000 { |
68 |
| - // Invalid data |
69 |
| - return Err(Error::InvalidData); |
| 59 | + if i + 1 >= len { |
| 60 | + // safe: len is the length of bytes, |
| 61 | + // and bytes is a direct view into the |
| 62 | + // buffer of input, which in order to be a valid |
| 63 | + // utf-8 string _must_ contain `i + 1`. |
| 64 | + unsafe { core::hint::unreachable_unchecked() } |
70 | 65 | }
|
| 66 | + |
71 | 67 | let a = u16::from(bytes[i] & 0b0001_1111);
|
72 | 68 | let b = u16::from(bytes[i + 1] & 0b0011_1111);
|
73 | 69 | ch = a << 6 | b;
|
74 | 70 | i += 2;
|
75 | 71 | } else if bytes[i] & 0b1111_0000 == 0b1110_0000 {
|
76 | 72 | // 3 byte codepoint
|
77 |
| - if i + 2 >= len { |
78 |
| - return Err(Error::BufferUnderflow); |
79 |
| - } |
80 |
| - if bytes[i + 1] & 0b1100_0000 != 0b1000_0000 |
81 |
| - || bytes[i + 2] & 0b1100_0000 != 0b1000_0000 |
82 |
| - { |
83 |
| - // Invalid data |
84 |
| - return Err(Error::InvalidData); |
| 73 | + if i + 2 >= len || i + 1 >= len { |
| 74 | + // safe: impossible utf-8 string. |
| 75 | + unsafe { core::hint::unreachable_unchecked() } |
85 | 76 | }
|
| 77 | + |
86 | 78 | let a = u16::from(bytes[i] & 0b0000_1111);
|
87 | 79 | let b = u16::from(bytes[i + 1] & 0b0011_1111);
|
88 | 80 | let c = u16::from(bytes[i + 2] & 0b0011_1111);
|
|
91 | 83 | } else if bytes[i] & 0b1111_0000 == 0b1111_0000 {
|
92 | 84 | return Err(Error::MultiByte); // UTF-16
|
93 | 85 | } else {
|
94 |
| - return Err(Error::InvalidData); |
| 86 | + // safe: impossible utf-8 string. |
| 87 | + unsafe { core::hint::unreachable_unchecked() } |
95 | 88 | }
|
96 | 89 | output(ch)?;
|
97 | 90 | }
|
|
0 commit comments