qubit_codec_text/charset/unicode.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8/// Namespace for Unicode constants and encoding-independent code point helpers.
9pub enum Unicode {}
10
11impl Unicode {
12 /// Maximum valid Unicode code point.
13 pub const MAX_CODE_POINT: u32 = 0x10ffff;
14
15 /// Unicode replacement character.
16 pub const REPLACEMENT_CHARACTER: char = '\u{fffd}';
17
18 /// Unicode byte order mark character.
19 pub const BOM: char = '\u{feff}';
20
21 /// Maximum valid ASCII code point.
22 pub const ASCII_MAX: u32 = 0x7f;
23
24 /// Maximum valid Latin-1 code point.
25 pub const LATIN1_MAX: u32 = 0xff;
26
27 /// Minimum supplementary code point.
28 pub const SUPPLEMENTARY_MIN: u32 = 0x10000;
29
30 /// Minimum high-surrogate code unit value.
31 pub const HIGH_SURROGATE_MIN: u32 = 0xd800;
32
33 /// Maximum high-surrogate code unit value.
34 pub const HIGH_SURROGATE_MAX: u32 = 0xdbff;
35
36 /// Minimum low-surrogate code unit value.
37 pub const LOW_SURROGATE_MIN: u32 = 0xdc00;
38
39 /// Maximum low-surrogate code unit value.
40 pub const LOW_SURROGATE_MAX: u32 = 0xdfff;
41
42 /// Minimum surrogate code unit value.
43 pub const SURROGATE_MIN: u32 = Self::HIGH_SURROGATE_MIN;
44
45 /// Maximum surrogate code unit value.
46 pub const SURROGATE_MAX: u32 = Self::LOW_SURROGATE_MAX;
47
48 /// Tests whether `value` is in the Unicode code point range.
49 ///
50 /// # Parameters
51 ///
52 /// - `value`: The raw code point value to test.
53 ///
54 /// # Returns
55 ///
56 /// Returns `true` for values in `0x0000..=0x10FFFF`, including surrogate
57 /// code points.
58 #[inline(always)]
59 pub const fn is_code_point(value: u32) -> bool {
60 value <= Self::MAX_CODE_POINT
61 }
62
63 /// Tests whether `value` is a valid Unicode scalar value.
64 ///
65 /// # Parameters
66 ///
67 /// - `value`: The raw code point value to test.
68 ///
69 /// # Returns
70 ///
71 /// Returns `true` for Unicode code points excluding UTF-16 surrogate
72 /// values.
73 #[inline(always)]
74 pub const fn is_scalar_value(value: u32) -> bool {
75 Self::is_code_point(value) && !Self::is_surrogate(value)
76 }
77
78 /// Tests whether `value` is a UTF-16 surrogate code point.
79 ///
80 /// # Parameters
81 ///
82 /// - `value`: The raw code point or code-unit value to test.
83 ///
84 /// # Returns
85 ///
86 /// Returns `true` if `value` is in `0xD800..=0xDFFF`.
87 #[inline(always)]
88 pub const fn is_surrogate(value: u32) -> bool {
89 value >= Self::SURROGATE_MIN && value <= Self::SURROGATE_MAX
90 }
91
92 /// Tests whether `value` is a high surrogate.
93 ///
94 /// # Parameters
95 ///
96 /// - `value`: The raw code point or code-unit value to test.
97 ///
98 /// # Returns
99 ///
100 /// Returns `true` if `value` is in `0xD800..=0xDBFF`.
101 #[inline(always)]
102 pub const fn is_high_surrogate(value: u32) -> bool {
103 value >= Self::HIGH_SURROGATE_MIN && value <= Self::HIGH_SURROGATE_MAX
104 }
105
106 /// Tests whether `value` is a low surrogate.
107 ///
108 /// # Parameters
109 ///
110 /// - `value`: The raw code point or code-unit value to test.
111 ///
112 /// # Returns
113 ///
114 /// Returns `true` if `value` is in `0xDC00..=0xDFFF`.
115 #[inline(always)]
116 pub const fn is_low_surrogate(value: u32) -> bool {
117 value >= Self::LOW_SURROGATE_MIN && value <= Self::LOW_SURROGATE_MAX
118 }
119
120 /// Tests whether `value` is in the basic multilingual plane.
121 ///
122 /// # Parameters
123 ///
124 /// - `value`: The raw code point value to test.
125 ///
126 /// # Returns
127 ///
128 /// Returns `true` if `value` is in `0x0000..=0xFFFF`.
129 #[inline(always)]
130 pub const fn is_bmp(value: u32) -> bool {
131 value < Self::SUPPLEMENTARY_MIN
132 }
133
134 /// Tests whether `value` is a supplementary Unicode code point.
135 ///
136 /// # Parameters
137 ///
138 /// - `value`: The raw code point value to test.
139 ///
140 /// # Returns
141 ///
142 /// Returns `true` if `value` is in `0x10000..=0x10FFFF`.
143 #[inline(always)]
144 pub const fn is_supplementary(value: u32) -> bool {
145 value >= Self::SUPPLEMENTARY_MIN && value <= Self::MAX_CODE_POINT
146 }
147
148 /// Tests whether `value` is an ASCII code point.
149 ///
150 /// # Parameters
151 ///
152 /// - `value`: The raw code point value to test.
153 ///
154 /// # Returns
155 ///
156 /// Returns `true` if `value` is in `0x00..=0x7F`.
157 #[inline(always)]
158 pub const fn is_ascii(value: u32) -> bool {
159 value <= Self::ASCII_MAX
160 }
161
162 /// Tests whether `value` is a Unicode noncharacter.
163 ///
164 /// # Parameters
165 ///
166 /// - `value`: The raw code point value to test.
167 ///
168 /// # Returns
169 ///
170 /// Returns `true` for Unicode noncharacters such as `U+FDD0..=U+FDEF` and
171 /// code points ending in `FFFE` or `FFFF`.
172 #[inline(always)]
173 pub const fn is_noncharacter(value: u32) -> bool {
174 Self::is_code_point(value)
175 && ((value >= 0xfdd0 && value <= 0xfdef)
176 || (value & 0xfffe) == 0xfffe)
177 }
178
179 /// Tests whether `value` is a Unicode C0, C1, or DEL control code point.
180 ///
181 /// # Parameters
182 ///
183 /// - `value`: The raw code point value to test.
184 ///
185 /// # Returns
186 ///
187 /// Returns `true` for `U+0000..=U+001F`, `U+007F`, and `U+0080..=U+009F`.
188 #[inline(always)]
189 pub const fn is_control(value: u32) -> bool {
190 value <= 0x1f || (value >= 0x7f && value <= 0x9f)
191 }
192
193 /// Returns the Unicode plane containing `value`.
194 ///
195 /// # Parameters
196 ///
197 /// - `value`: The raw code point value to inspect.
198 ///
199 /// # Returns
200 ///
201 /// Returns `Some(plane)` for Unicode code points, or `None` for values
202 /// above `U+10FFFF`.
203 #[inline(always)]
204 pub const fn plane(value: u32) -> Option<u32> {
205 if Self::is_code_point(value) {
206 Some(value >> 16)
207 } else {
208 None
209 }
210 }
211
212 /// Converts a raw code point into a Rust `char`.
213 ///
214 /// # Parameters
215 ///
216 /// - `value`: The raw code point value to convert.
217 ///
218 /// # Returns
219 ///
220 /// Returns `Some(char)` for valid Unicode scalar values and `None`
221 /// otherwise.
222 #[inline(always)]
223 pub fn to_char(value: u32) -> Option<char> {
224 char::from_u32(value)
225 }
226}