Parse and decode a unicode char that's encoded as octal triplets. For example, 🌠 translates to `\360\237\214\240`, which is equivalent to `0xf0 0x9f 0x8c 0xa0` hex encoding. Each triplet represents a single UTF-8 byte segment, check [`octal_triplet`] for more details.
(input: &mut &str)
| 89 | /// |
| 90 | /// Each triplet represents a single UTF-8 byte segment, check [`octal_triplet`] for more details. |
| 91 | fn unicode_char(input: &mut &str) -> ModalResult<String> { |
| 92 | // A unicode char can consist of up to 4 bytes, which is what we use this buffer for. |
| 93 | let mut unicode_bytes = Vec::new(); |
| 94 | |
| 95 | // Create a checkpoint in case there's an error while decoding the whole |
| 96 | // byte sequence in the very end. |
| 97 | let checkpoint = input.checkpoint(); |
| 98 | |
| 99 | // Parse the first octal triplet into bytes. |
| 100 | // If the input isn't an octal triplet, we hit an unknown encoding and return a backtrack error |
| 101 | // for a better error message on a higher level. |
| 102 | let first = octal_triplet(input)?; |
| 103 | |
| 104 | unicode_bytes.push(first); |
| 105 | |
| 106 | // Get the number of leading ones, which determines the amount of following |
| 107 | // bytes in this unicode char. This amount of leading ones can be one of `[0, 2, 3, 4]`. |
| 108 | // Other values are forbidden. |
| 109 | let leading_ones: usize = first.leading_ones() as usize; |
| 110 | |
| 111 | // If there're no leading ones this char is a single byte UTF-8 char. |
| 112 | if leading_ones == 0 { |
| 113 | return bytes_to_string(input, checkpoint, unicode_bytes); |
| 114 | } |
| 115 | |
| 116 | // Make sure that we didn't get an invalid amount of leading zeroes |
| 117 | if leading_ones > 4 || leading_ones == 1 { |
| 118 | let mut error = ContextError::new(); |
| 119 | error = error.add_context( |
| 120 | input, |
| 121 | &checkpoint, |
| 122 | StrContext::Label("amount of leading zeroes in first UTF-8 byte"), |
| 123 | ); |
| 124 | return Err(ErrMode::Cut(error)); |
| 125 | } |
| 126 | |
| 127 | // Due to the amount of leading ones, we know how many bytes we have to expect. |
| 128 | // Parse the amount of expected bytes and throw an error if that didn't work out. |
| 129 | for _ in 1..leading_ones { |
| 130 | let byte = cut_err(octal_triplet) |
| 131 | .context(StrContext::Label("utf8 encoded byte")) |
| 132 | .context(StrContext::Expected(StrContextValue::Description( |
| 133 | "octal triplet encoded unicode byte.", |
| 134 | ))) |
| 135 | .parse_next(input)?; |
| 136 | |
| 137 | unicode_bytes.push(byte); |
| 138 | } |
| 139 | |
| 140 | // Read the bytes to string, which might result in another parser error. |
| 141 | bytes_to_string(input, checkpoint, unicode_bytes) |
| 142 | } |
| 143 | |
| 144 | /// Take the UTF-8 byte sequence and parse it into a `String`. |
| 145 | /// |
nothing calls this directly
no test coverage detected