MCPcopy Create free account
hub / github.com/archlinux/alpm / unicode_char

Function unicode_char

alpm-mtree/src/path_decoder.rs:91–142  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

89///
90/// Each triplet represents a single UTF-8 byte segment, check [`octal_triplet`] for more details.
91fn 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///

Callers

nothing calls this directly

Calls 2

octal_tripletFunction · 0.85
bytes_to_stringFunction · 0.85

Tested by

no test coverage detected