Skip to main content

utf_types/
utf16.rs

1// Copyright Mozilla Foundation
2//
3// Licensed under the Apache License (Version 2.0), or the MIT license,
4// (the "Licenses") at your option. You may not use this file except in
5// compliance with one of the Licenses. You may obtain copies of the
6// Licenses at:
7//
8//    https://www.apache.org/licenses/LICENSE-2.0
9//    https://opensource.org/licenses/MIT
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the Licenses is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the Licenses for the specific language governing permissions and
15// limitations under the Licenses.
16
17//! Types for UTF-16 code unit sequences and their parts.
18
19use core::fmt::Formatter;
20use core::num::NonZeroU16;
21
22/// A type for signaling UTF-16 errors.
23#[derive(#[automatically_derived]impl ::core::fmt::Debug for Utf16CodeUnitError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Utf16CodeUnitError")
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    Utf16CodeUnitError {
}
#[automatically_derived]impl ::core::cmp::PartialEq for Utf16CodeUnitError {
    #[inline]
    fn eq(&self, other: &Self) -> bool { true }
}PartialEq, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Utf16CodeUnitError {
}
#[automatically_derived]impl ::core::clone::Clone for Utf16CodeUnitError {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Utf16CodeUnitError { }Copy, #[automatically_derived]impl ::core::hash::Hash for Utf16CodeUnitError {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]impl ::core::cmp::Eq for Utf16CodeUnitError { }Eq)]
24#[non_exhaustive]
25pub struct Utf16CodeUnitError;
26
27impl core::fmt::Display for Utf16CodeUnitError {
28    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
29        f.write_fmt(format_args!("code unit does not fit the requested position in UTF-16"))write!(f, "code unit does not fit the requested position in UTF-16")
30    }
31}
32
33impl core::error::Error for Utf16CodeUnitError {}
34
35macro_rules! surrogate_impl {
36    ($min:expr,
37     $max:expr,
38     $(#[$is_meta:meta])*,
39     $(#[$unchecked_meta:meta])*,
40     $(#[$checked_meta:meta])*,
41    ) => {
42        /// Minimum possible value.
43        pub const MIN: Self = const {
44            if $min == 0 {
45                panic!();
46            }
47            Self {
48                code_unit: if let Some(min) = NonZeroU16::new($min) {
49                    min
50                } else {
51                    panic!();
52                },
53            }
54        };
55
56        /// Maximum possible value.
57        pub const MAX: Self = const {
58            Self {
59                code_unit: if let Some(max) = NonZeroU16::new($max) {
60                    max
61                } else {
62                    panic!();
63                },
64            }
65        };
66
67        $(#[$is_meta])*
68        #[inline(always)]
69        pub const fn is(code_unit: u16) -> bool {
70            code_unit >= Self::MIN.to_u16() && code_unit <= Self::MAX.to_u16()
71        }
72
73        $(#[$unchecked_meta])*
74        #[inline(always)]
75        pub const unsafe fn new_unchecked(code_unit: u16) -> Self {
76            debug_assert!(Self::is(code_unit));
77            // INVARIANT UPHELD: The range is this function's safety invariant.
78            // SAFETY: The range is enforced via `MIN` (and `MAX`), and `MIN` is checked
79            // not to be zero in its `const` initialization.
80            Self { code_unit: unsafe { NonZeroU16::new_unchecked(code_unit) } }
81        }
82
83        $(#[$checked_meta])*
84        #[inline(always)]
85        pub const fn try_new(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
86            if Self::is(code_unit) {
87                // SAFETY: We checked the safety invariant immediately above.
88                Ok(unsafe { Self::new_unchecked(code_unit) })
89            } else {
90                Err(Utf16CodeUnitError)
91            }
92        }
93
94        /// Convert to plain code unit
95        #[inline(always)]
96        pub const fn to_u16(self) -> u16 {
97            self.code_unit.get()
98        }
99    };
100}
101
102macro_rules! to_surrogate {
103    () => {
104        /// Convert to `Surrogate`
105        #[inline(always)]
106        pub const fn to_surrogate(self) -> Surrogate {
107            // INVARIANT UPHELD: `Self` has a stricter invariant than the target
108            // type, so the conversion is safe.
109            Surrogate {
110                code_unit: self.code_unit,
111            }
112        }
113    };
114}
115
116macro_rules! code_unit_impls {
117    ($type:ident,
118     $type_specific_ident:ident,
119    ) => {
120        impl TryFrom<u16> for $type {
121            type Error = Utf16CodeUnitError;
122
123            #[inline(always)]
124            fn try_from(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
125                Self::try_new(code_unit)
126            }
127        }
128
129        impl From<$type> for u16 {
130            #[inline(always)]
131            fn from($type_specific_ident: $type) -> Self {
132                $type_specific_ident.to_u16()
133            }
134        }
135    };
136}
137
138/// For making sure that reviewing this file is sufficient for
139/// reviewing the implementations of `Utf16CodeUnitSequence`.
140trait Seal {}
141
142/// Common output conversions for both UTF-16 code unit sequences.
143#[allow(private_bounds)] // allow sealing
144pub trait Utf16CodeUnitSequence: Seal + Copy + Clone + Into<char> + AsRef<[u16]> {}
145
146macro_rules! sequence_impls {
147    ($type:ident,
148     $type_specific_ident:ident,
149    ) => {
150        impl Seal for $type {}
151
152        impl Utf16CodeUnitSequence for $type {}
153
154        impl From<$type> for char {
155            #[inline(always)]
156            fn from($type_specific_ident: $type) -> Self {
157                $type_specific_ident.to_char()
158            }
159        }
160
161        impl AsRef<[u16]> for $type {
162            #[inline(always)]
163            fn as_ref(&self) -> &[u16] {
164                self.as_slice()
165            }
166        }
167    };
168}
169
170/// A single-code-unit UTF-16 sequence representing a (non-surrogate)
171/// character in the Basic Multilingual Plane.
172#[derive(#[automatically_derived]impl ::core::fmt::Debug for Bmp {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "Bmp code_unit",
            &&self.code_unit)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Bmp {
}
#[automatically_derived]impl ::core::clone::Clone for Bmp {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<u16>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Bmp { }Copy, #[automatically_derived]impl ::core::hash::Hash for Bmp {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.code_unit, state)
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for Bmp {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u16>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for Bmp { }
#[automatically_derived]impl ::core::cmp::PartialEq for Bmp {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.code_unit == other.code_unit }
}PartialEq, #[automatically_derived]impl ::core::cmp::Ord for Bmp {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.code_unit, &other.code_unit)
    }
}Ord, #[automatically_derived]impl ::core::cmp::PartialOrd for Bmp {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
173#[repr(transparent)]
174pub struct Bmp {
175    /// # Safety invariant
176    ///
177    /// Not a surrogate.
178    code_unit: u16, // Would be nice to have a niche without hurting perf
179}
180
181impl Bmp {
182    /// Whether `code_unit` is in range for this type (not a surrogate)
183    ///
184    /// # Safety-usable invariant
185    ///
186    /// Iff this method returns `true`, the safety invariant of `new_unchecked()`
187    /// is satisfied.
188    #[inline(always)]
189    pub const fn is(code_unit: u16) -> bool {
190        !Surrogate::is(code_unit)
191    }
192
193    /// Unchecked constructor
194    ///
195    /// # Safety
196    ///
197    /// The caller must ensure that `code_unit` is _not_ in the range `0xD800..=0xDFFF`.
198    ///
199    /// # Panics
200    ///
201    /// When debug assertions are enabled, panics if the safety invariant
202    /// is not upheld.
203    #[inline(always)]
204    pub const unsafe fn new_unchecked(code_unit: u16) -> Self {
205        if true {
    if !Self::is(code_unit) {
        ::core::panicking::panic("assertion failed: Self::is(code_unit)")
    };
};debug_assert!(Self::is(code_unit));
206        // INVARIANT UPHELD: The range is this function's safety invariant.
207        Self { code_unit }
208    }
209
210    /// Fallible constructor
211    ///
212    /// `Ok` if _not_ surrogate and `Err` otherwise.
213    #[inline(always)]
214    pub const fn try_new(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
215        if Self::is(code_unit) {
216            // SAFETY: We checked the safety invariant immediately above.
217            Ok(unsafe { Self::new_unchecked(code_unit) })
218        } else {
219            Err(Utf16CodeUnitError)
220        }
221    }
222
223    /// Convert to plain code unit
224    #[inline(always)]
225    pub const fn to_u16(self) -> u16 {
226        self.code_unit
227    }
228
229    /// Convert to `char`
230    #[inline(always)]
231    pub const fn to_char(self) -> char {
232        let scalar = self.code_unit as u32;
233        if true {
    if !char::from_u32(scalar).is_some() {
        ::core::panicking::panic("assertion failed: char::from_u32(scalar).is_some()")
    };
};debug_assert!(char::from_u32(scalar).is_some());
234        // SAFETY: The invariant of `Bmp` guarantees that
235        // we don't have a surrogate, so `scalar` is indeed
236        // a Unicode scalar value.
237        unsafe { char::from_u32_unchecked(scalar) }
238    }
239
240    /// View as `&[u16]`
241    #[inline(always)]
242    pub const fn as_slice(&self) -> &[u16] {
243        core::slice::from_ref(&self.code_unit)
244    }
245}
246
247impl TryFrom<u16> for Bmp {
    type Error = Utf16CodeUnitError;
    #[inline(always)]
    fn try_from(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
        Self::try_new(code_unit)
    }
}
impl From<Bmp> for u16 {
    #[inline(always)]
    fn from(bmp: Bmp) -> Self { bmp.to_u16() }
}code_unit_impls!(Bmp, bmp,);
248
249impl Seal for Bmp {}
impl Utf16CodeUnitSequence for Bmp {}
impl From<Bmp> for char {
    #[inline(always)]
    fn from(bmp: Bmp) -> Self { bmp.to_char() }
}
impl AsRef<[u16]> for Bmp {
    #[inline(always)]
    fn as_ref(&self) -> &[u16] { self.as_slice() }
}sequence_impls!(Bmp, bmp,);
250
251/// A single surrogate code unit, which can be a high
252/// surrogate or a low surrogate
253#[derive(#[automatically_derived]impl ::core::fmt::Debug for Surrogate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "Surrogate code_unit", &&self.code_unit)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Surrogate {
}
#[automatically_derived]impl ::core::clone::Clone for Surrogate {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<NonZeroU16>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Surrogate { }Copy, #[automatically_derived]impl ::core::hash::Hash for Surrogate {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.code_unit, state)
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for Surrogate {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZeroU16>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for Surrogate
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for Surrogate {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.code_unit == other.code_unit }
}PartialEq, #[automatically_derived]impl ::core::cmp::Ord for Surrogate {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.code_unit, &other.code_unit)
    }
}Ord, #[automatically_derived]impl ::core::cmp::PartialOrd for Surrogate {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
254#[repr(transparent)]
255pub struct Surrogate {
256    /// # Safety invariant
257    ///
258    /// A surrogate.
259    code_unit: NonZeroU16,
260}
261
262impl Surrogate {
263    /// Minimum possible value.
pub const MIN: Self =
    const {
            if 0xD800 == 0 { ::core::panicking::panic_default_msg(); }
            Self {
                code_unit: if let Some(min) = NonZeroU16::new(0xD800) {
                    min
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
/// Maximum possible value.
pub const MAX: Self =
    const {
            Self {
                code_unit: if let Some(max) = NonZeroU16::new(0xDFFF) {
                    max
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
#[doc = r" Whether `code_unit` is a surrogate."]
#[doc = r""]
#[doc = r" # Safety-usable invariant"]
#[doc = r""]
#[doc =
r" Iff this method returns `true`, the safety invariant of `new_unchecked()`"]
#[doc = r" is satisfied."]
#[inline(always)]
pub const fn is(code_unit: u16) -> bool {
    code_unit >= Self::MIN.to_u16() && code_unit <= Self::MAX.to_u16()
}
#[doc = r" Unchecked constructor"]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The caller must ensure that `code_unit` is in the range `0xD800..=0xDFFF`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" When debug assertions are enabled, panics if the safety invariant"]
#[doc = r" is not upheld."]
#[inline(always)]
pub const unsafe fn new_unchecked(code_unit: u16) -> Self {
    if true {
        if !Self::is(code_unit) {
            ::core::panicking::panic("assertion failed: Self::is(code_unit)")
        };
    };
    Self { code_unit: unsafe { NonZeroU16::new_unchecked(code_unit) } }
}
#[doc = r" Fallible constructor"]
#[doc = r""]
#[doc = r" `Ok` if surrogate and `Err` otherwise."]
#[inline(always)]
pub const fn try_new(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
    if Self::is(code_unit) {
        Ok(unsafe { Self::new_unchecked(code_unit) })
    } else { Err(Utf16CodeUnitError) }
}
/// Convert to plain code unit
#[inline(always)]
pub const fn to_u16(self) -> u16 { self.code_unit.get() }surrogate_impl!(
264        0xD800,
265        0xDFFF,
266        /// Whether `code_unit` is a surrogate.
267        ///
268        /// # Safety-usable invariant
269        ///
270        /// Iff this method returns `true`, the safety invariant of `new_unchecked()`
271        /// is satisfied.
272        ,
273        /// Unchecked constructor
274        ///
275        /// # Safety
276        ///
277        /// The caller must ensure that `code_unit` is in the range `0xD800..=0xDFFF`.
278        ///
279        /// # Panics
280        ///
281        /// When debug assertions are enabled, panics if the safety invariant
282        /// is not upheld.
283        ,
284        /// Fallible constructor
285        ///
286        /// `Ok` if surrogate and `Err` otherwise.
287        ,
288    );
289}
290
291impl TryFrom<u16> for Surrogate {
    type Error = Utf16CodeUnitError;
    #[inline(always)]
    fn try_from(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
        Self::try_new(code_unit)
    }
}
impl From<Surrogate> for u16 {
    #[inline(always)]
    fn from(surrogate: Surrogate) -> Self { surrogate.to_u16() }
}code_unit_impls!(Surrogate, surrogate,);
292
293/// A high surrogate
294#[derive(#[automatically_derived]impl ::core::fmt::Debug for HighSurrogate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "HighSurrogate code_unit", &&self.code_unit)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for HighSurrogate {
}
#[automatically_derived]impl ::core::clone::Clone for HighSurrogate {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<NonZeroU16>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for HighSurrogate { }Copy, #[automatically_derived]impl ::core::hash::Hash for HighSurrogate {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.code_unit, state)
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for HighSurrogate {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZeroU16>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    HighSurrogate {
}
#[automatically_derived]impl ::core::cmp::PartialEq for HighSurrogate {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.code_unit == other.code_unit }
}PartialEq, #[automatically_derived]impl ::core::cmp::Ord for HighSurrogate {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.code_unit, &other.code_unit)
    }
}Ord, #[automatically_derived]impl ::core::cmp::PartialOrd for HighSurrogate {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
295#[repr(transparent)]
296pub struct HighSurrogate {
297    /// # Safety invariant
298    ///
299    /// A high surrogate.
300    code_unit: NonZeroU16,
301}
302
303impl HighSurrogate {
304    /// Minimum possible value.
pub const MIN: Self =
    const {
            if 0xD800 == 0 { ::core::panicking::panic_default_msg(); }
            Self {
                code_unit: if let Some(min) = NonZeroU16::new(0xD800) {
                    min
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
/// Maximum possible value.
pub const MAX: Self =
    const {
            Self {
                code_unit: if let Some(max) = NonZeroU16::new(0xDBFF) {
                    max
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
#[doc = r" Whether `code_unit` is a high surrogate."]
#[doc = r""]
#[doc = r" # Safety-usable invariant"]
#[doc = r""]
#[doc =
r" Iff this method returns `true`, the safety invariant of `new_unchecked()`"]
#[doc = r" is satisfied."]
#[inline(always)]
pub const fn is(code_unit: u16) -> bool {
    code_unit >= Self::MIN.to_u16() && code_unit <= Self::MAX.to_u16()
}
#[doc = r" Unchecked constructor"]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The caller must ensure that `code_unit` is in the range `0xD800..=0xDBFF`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" When debug assertions are enabled, panics if the safety invariant"]
#[doc = r" is not upheld."]
#[inline(always)]
pub const unsafe fn new_unchecked(code_unit: u16) -> Self {
    if true {
        if !Self::is(code_unit) {
            ::core::panicking::panic("assertion failed: Self::is(code_unit)")
        };
    };
    Self { code_unit: unsafe { NonZeroU16::new_unchecked(code_unit) } }
}
#[doc = r" Fallible constructor"]
#[doc = r""]
#[doc = r" `Ok` if high surrogate and `Err` otherwise."]
#[inline(always)]
pub const fn try_new(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
    if Self::is(code_unit) {
        Ok(unsafe { Self::new_unchecked(code_unit) })
    } else { Err(Utf16CodeUnitError) }
}
/// Convert to plain code unit
#[inline(always)]
pub const fn to_u16(self) -> u16 { self.code_unit.get() }surrogate_impl!(
305        0xD800,
306        0xDBFF,
307        /// Whether `code_unit` is a high surrogate.
308        ///
309        /// # Safety-usable invariant
310        ///
311        /// Iff this method returns `true`, the safety invariant of `new_unchecked()`
312        /// is satisfied.
313        ,
314        /// Unchecked constructor
315        ///
316        /// # Safety
317        ///
318        /// The caller must ensure that `code_unit` is in the range `0xD800..=0xDBFF`.
319        ///
320        /// # Panics
321        ///
322        /// When debug assertions are enabled, panics if the safety invariant
323        /// is not upheld.
324        ,
325        /// Fallible constructor
326        ///
327        /// `Ok` if high surrogate and `Err` otherwise.
328        ,
329    );
330
331    /// Convert to `Surrogate`
#[inline(always)]
pub const fn to_surrogate(self) -> Surrogate {
    Surrogate { code_unit: self.code_unit }
}to_surrogate!();
332
333    /// Fallible constructor given a surrogate
334    ///
335    /// `Ok` if high surrogate and `Err` otherwise.
336    #[inline(always)]
337    pub const fn try_new_with_surrogate(surrogate: Surrogate) -> Result<Self, Utf16CodeUnitError> {
338        let code_unit = surrogate.to_u16();
339        if code_unit <= Self::MAX.to_u16() {
340            // SAFETY: We checked the safety invariant immediately above (the other end
341            // of the range comes from the field invariant of `Surrogate`).
342            Ok(unsafe { Self::new_unchecked(code_unit) })
343        } else {
344            Err(Utf16CodeUnitError)
345        }
346    }
347}
348
349impl TryFrom<u16> for HighSurrogate {
    type Error = Utf16CodeUnitError;
    #[inline(always)]
    fn try_from(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
        Self::try_new(code_unit)
    }
}
impl From<HighSurrogate> for u16 {
    #[inline(always)]
    fn from(high_surrogate: HighSurrogate) -> Self { high_surrogate.to_u16() }
}code_unit_impls!(HighSurrogate, high_surrogate,);
350
351/// A low surrogate
352#[derive(#[automatically_derived]impl ::core::fmt::Debug for LowSurrogate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "LowSurrogate code_unit", &&self.code_unit)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for LowSurrogate {
}
#[automatically_derived]impl ::core::clone::Clone for LowSurrogate {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<NonZeroU16>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for LowSurrogate { }Copy, #[automatically_derived]impl ::core::hash::Hash for LowSurrogate {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.code_unit, state)
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for LowSurrogate {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZeroU16>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    LowSurrogate {
}
#[automatically_derived]impl ::core::cmp::PartialEq for LowSurrogate {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.code_unit == other.code_unit }
}PartialEq, #[automatically_derived]impl ::core::cmp::Ord for LowSurrogate {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.code_unit, &other.code_unit)
    }
}Ord, #[automatically_derived]impl ::core::cmp::PartialOrd for LowSurrogate {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
353#[repr(transparent)]
354pub struct LowSurrogate {
355    /// # Safety invariant
356    ///
357    /// A low surrogate.
358    code_unit: NonZeroU16,
359}
360
361impl LowSurrogate {
362    /// Minimum possible value.
pub const MIN: Self =
    const {
            if 0xDC00 == 0 { ::core::panicking::panic_default_msg(); }
            Self {
                code_unit: if let Some(min) = NonZeroU16::new(0xDC00) {
                    min
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
/// Maximum possible value.
pub const MAX: Self =
    const {
            Self {
                code_unit: if let Some(max) = NonZeroU16::new(0xDFFF) {
                    max
                } else { ::core::panicking::panic_default_msg(); },
            }
        };
#[doc = r" Whether `code_unit` is a low surrogate."]
#[doc = r""]
#[doc = r" # Safety-usable invariant"]
#[doc = r""]
#[doc =
r" Iff this method returns `true`, the safety invariant of `new_unchecked()`"]
#[doc = r" is satisfied."]
#[inline(always)]
pub const fn is(code_unit: u16) -> bool {
    code_unit >= Self::MIN.to_u16() && code_unit <= Self::MAX.to_u16()
}
#[doc = r" Unchecked constructor"]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The caller must ensure that `code_unit` is in the range `0xDC00..=0xDFFF`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" When debug assertions are enabled, panics if the safety invariant"]
#[doc = r" is not upheld."]
#[inline(always)]
pub const unsafe fn new_unchecked(code_unit: u16) -> Self {
    if true {
        if !Self::is(code_unit) {
            ::core::panicking::panic("assertion failed: Self::is(code_unit)")
        };
    };
    Self { code_unit: unsafe { NonZeroU16::new_unchecked(code_unit) } }
}
#[doc = r" Fallible constructor"]
#[doc = r""]
#[doc = r" `Ok` if low surrogate and `Err` otherwise."]
#[inline(always)]
pub const fn try_new(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
    if Self::is(code_unit) {
        Ok(unsafe { Self::new_unchecked(code_unit) })
    } else { Err(Utf16CodeUnitError) }
}
/// Convert to plain code unit
#[inline(always)]
pub const fn to_u16(self) -> u16 { self.code_unit.get() }surrogate_impl!(
363        0xDC00,
364        0xDFFF,
365        /// Whether `code_unit` is a low surrogate.
366        ///
367        /// # Safety-usable invariant
368        ///
369        /// Iff this method returns `true`, the safety invariant of `new_unchecked()`
370        /// is satisfied.
371        ,
372        /// Unchecked constructor
373        ///
374        /// # Safety
375        ///
376        /// The caller must ensure that `code_unit` is in the range `0xDC00..=0xDFFF`.
377        ///
378        /// # Panics
379        ///
380        /// When debug assertions are enabled, panics if the safety invariant
381        /// is not upheld.
382        ,
383        /// Fallible constructor
384        ///
385        /// `Ok` if low surrogate and `Err` otherwise.
386        ,
387    );
388
389    /// Convert to `Surrogate`
#[inline(always)]
pub const fn to_surrogate(self) -> Surrogate {
    Surrogate { code_unit: self.code_unit }
}to_surrogate!();
390
391    /// Fallible constructor given a surrogate
392    ///
393    /// `Ok` if low surrogate and `Err` otherwise.
394    #[inline(always)]
395    pub const fn try_new_with_surrogate(surrogate: Surrogate) -> Result<Self, Utf16CodeUnitError> {
396        let code_unit = surrogate.to_u16();
397        if code_unit >= Self::MIN.to_u16() {
398            // SAFETY: We checked the safety invariant immediately above (the other end
399            // of the range comes from the field invariant of `Surrogate`).
400            Ok(unsafe { Self::new_unchecked(code_unit) })
401        } else {
402            Err(Utf16CodeUnitError)
403        }
404    }
405}
406
407impl TryFrom<u16> for LowSurrogate {
    type Error = Utf16CodeUnitError;
    #[inline(always)]
    fn try_from(code_unit: u16) -> Result<Self, Utf16CodeUnitError> {
        Self::try_new(code_unit)
    }
}
impl From<LowSurrogate> for u16 {
    #[inline(always)]
    fn from(low_surrogate: LowSurrogate) -> Self { low_surrogate.to_u16() }
}code_unit_impls!(LowSurrogate, low_surrogate,);
408
409/// A two-code-unit UTF-16 sequence
410///
411/// A high surrogate followed by a low surrogate representing
412/// a Unicode scalar value outside the Basic Multilingual Plane.
413#[derive(#[automatically_derived]impl ::core::fmt::Debug for SurrogatePair {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "SurrogatePair high low", &self.high, &&self.low)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for SurrogatePair {
}
#[automatically_derived]impl ::core::clone::Clone for SurrogatePair {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<HighSurrogate>;
        let _: ::core::clone::AssertParamIsClone<LowSurrogate>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for SurrogatePair { }Copy, #[automatically_derived]impl ::core::hash::Hash for SurrogatePair {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.high, state);
        ::core::hash::Hash::hash(&self.low, state)
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for SurrogatePair {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<HighSurrogate>;
        let _: ::core::cmp::AssertParamIsEq<LowSurrogate>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    SurrogatePair {
}
#[automatically_derived]impl ::core::cmp::PartialEq for SurrogatePair {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.high == other.high && self.low == other.low
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Ord for SurrogatePair {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.high, &other.high) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.low, &other.low),
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]impl ::core::cmp::PartialOrd for SurrogatePair {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
414#[repr(C)]
415pub struct SurrogatePair {
416    high: HighSurrogate,
417    low: LowSurrogate,
418}
419
420impl SurrogatePair {
421    /// Constructor from a high surrogate and a low surrogate
422    #[inline(always)]
423    pub const fn new(high: HighSurrogate, low: LowSurrogate) -> Self {
424        Self { high, low }
425    }
426
427    /// Convert to typed code unit tuple.
428    #[inline(always)]
429    pub const fn to_typed_code_units(self) -> (HighSurrogate, LowSurrogate) {
430        (self.high, self.low)
431    }
432
433    /// Convert to `char`
434    #[inline(always)]
435    pub const fn to_char(self) -> char {
436        let scalar = ((self.high.to_u16() as u32) << 10) + (self.low.to_u16() as u32)
437            - (((0xD800u32 << 10) - 0x10000u32) + 0xDC00u32);
438        if true {
    if !char::from_u32(scalar).is_some() {
        ::core::panicking::panic("assertion failed: char::from_u32(scalar).is_some()")
    };
};debug_assert!(char::from_u32(scalar).is_some());
439        // SAFETY: The above formulation results in a value in the `char` range given
440        // the value range invariants of `HighSurrogate` and `LowSurrogate`.
441        unsafe { char::from_u32_unchecked(scalar) }
442    }
443
444    /// View as `&[u16; 2]`
445    ///
446    /// # Safety-usable invariant
447    ///
448    /// The array contains a single well-formed surrogate pair.
449    #[inline(always)]
450    pub const fn as_code_units(&self) -> &[u16; 2] {
451        if core::mem::size_of::<Self>() != core::mem::size_of::<[u16; 2]>() {
452            ::core::panicking::panic_default_msg();panic!();
453        }
454        let ptr: *const Self = core::ptr::from_ref(self);
455        // SAFETY: The `repr` of `Self` guarantees that it
456        // is safe to view `Self` as `[u16; 2]`.
457        unsafe { &*ptr.cast() }
458    }
459
460    /// View as `&[u16]`
461    ///
462    /// # Safety-usable invariant
463    ///
464    /// The slice contains a single well-formed surrogate pair.
465    #[inline(always)]
466    pub const fn as_slice(&self) -> &[u16] {
467        self.as_code_units()
468    }
469}
470
471impl Seal for SurrogatePair {}
impl Utf16CodeUnitSequence for SurrogatePair {}
impl From<SurrogatePair> for char {
    #[inline(always)]
    fn from(surrogate_pair: SurrogatePair) -> Self {
        surrogate_pair.to_char()
    }
}
impl AsRef<[u16]> for SurrogatePair {
    #[inline(always)]
    fn as_ref(&self) -> &[u16] { self.as_slice() }
}sequence_impls!(SurrogatePair, surrogate_pair,);
472
473// Separate type to keep the `try_new` constructors consistent in `Err()` containing
474// an actual error type and to not characterize surrogates as errors.
475
476/// Type for categorizing code units as either non-surrogates or surrogates.
477#[derive(#[automatically_derived]impl ::core::fmt::Debug for BmpOrSurrogate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Bmp(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Bmp",
                    &__self_0),
            Self::Surrogate(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Surrogate", &__self_0),
        }
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for BmpOrSurrogate {
}
#[automatically_derived]impl ::core::clone::Clone for BmpOrSurrogate {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Bmp>;
        let _: ::core::clone::AssertParamIsClone<Surrogate>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for BmpOrSurrogate { }Copy, #[automatically_derived]impl ::core::hash::Hash for BmpOrSurrogate {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state);
        match self {
            Self::Bmp(__self_0) => ::core::hash::Hash::hash(__self_0, state),
            Self::Surrogate(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]impl ::core::cmp::Eq for BmpOrSurrogate {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Bmp>;
        let _: ::core::cmp::AssertParamIsEq<Surrogate>;
    }
}Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    BmpOrSurrogate {
}
#[automatically_derived]impl ::core::cmp::PartialEq for BmpOrSurrogate {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Bmp(__self_0), Self::Bmp(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::Surrogate(__self_0), Self::Surrogate(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
478pub enum BmpOrSurrogate {
479    /// Non-surrogate code unit on the Basic Multilingual Plane
480    Bmp(Bmp),
481    /// Surrogate
482    Surrogate(Surrogate),
483}
484
485impl BmpOrSurrogate {
486    /// Constructor
487    #[inline(always)]
488    pub const fn new(code_unit: u16) -> Self {
489        if Bmp::is(code_unit) {
490            // SAFETY: We checked the invariant above.
491            Self::Bmp(unsafe { Bmp::new_unchecked(code_unit) })
492        } else {
493            // SAFETY: We checked the invariant above.
494            Self::Surrogate(unsafe { Surrogate::new_unchecked(code_unit) })
495        }
496    }
497}
498
499// TODO: Add 16-bit types that correspond to the value ranges of 1, 2, and 3-byte
500// UTF-8 sequences.
501
502#[cfg(test)]
503mod tests {
504    use super::*;
505
506    #[test]
507    fn test_code_unit_ranges() {
508        for u in 0..=0xFFFFu16 {
509            let surrogate = (0xD800..=0xDFFF).contains(&u);
510            let high = (0xD800..=0xDBFF).contains(&u);
511            let low = (0xDC00..=0xDFFF).contains(&u);
512
513            assert_eq!(Bmp::is(u), !surrogate);
514            assert_eq!(Surrogate::is(u), surrogate);
515            assert_eq!(HighSurrogate::is(u), high);
516            assert_eq!(LowSurrogate::is(u), low);
517
518            assert_eq!(
519                Bmp::try_new(u).map(Bmp::to_u16),
520                Bmp::is(u).then_some(u).ok_or(Utf16CodeUnitError)
521            );
522            assert_eq!(
523                Surrogate::try_new(u).map(Surrogate::to_u16),
524                surrogate.then_some(u).ok_or(Utf16CodeUnitError)
525            );
526            assert_eq!(
527                HighSurrogate::try_new(u).map(HighSurrogate::to_u16),
528                high.then_some(u).ok_or(Utf16CodeUnitError)
529            );
530            assert_eq!(
531                LowSurrogate::try_new(u).map(LowSurrogate::to_u16),
532                low.then_some(u).ok_or(Utf16CodeUnitError)
533            );
534
535            match BmpOrSurrogate::new(u) {
536                BmpOrSurrogate::Bmp(bmp) => {
537                    assert!(!surrogate);
538                    assert_eq!(bmp.to_u16(), u);
539                    assert_eq!(Some(bmp.to_char()), char::from_u32(u as u32));
540                    assert_eq!(bmp.as_slice(), &[u]);
541                }
542                BmpOrSurrogate::Surrogate(s) => {
543                    assert!(surrogate);
544                    assert_eq!(s.to_u16(), u);
545                    assert_eq!(
546                        HighSurrogate::try_new_with_surrogate(s).map(HighSurrogate::to_u16),
547                        high.then_some(u).ok_or(Utf16CodeUnitError)
548                    );
549                    assert_eq!(
550                        LowSurrogate::try_new_with_surrogate(s).map(LowSurrogate::to_u16),
551                        low.then_some(u).ok_or(Utf16CodeUnitError)
552                    );
553                    if let Ok(h) = HighSurrogate::try_new(u) {
554                        assert_eq!(h.to_surrogate(), s);
555                    }
556                    if let Ok(l) = LowSurrogate::try_new(u) {
557                        assert_eq!(l.to_surrogate(), s);
558                    }
559                }
560            }
561        }
562    }
563
564    #[test]
565    fn test_surrogate_pairs() {
566        let mut previous: Option<(SurrogatePair, char)> = None;
567        for high in 0xD800..=0xDBFFu16 {
568            for low in 0xDC00..=0xDFFFu16 {
569                let pair = SurrogatePair::new(
570                    HighSurrogate::try_new(high).unwrap(),
571                    LowSurrogate::try_new(low).unwrap(),
572                );
573                let expected = char::decode_utf16([high, low]).next().unwrap().unwrap();
574                let c = pair.to_char();
575                assert_eq!(c, expected);
576                assert_eq!(pair.as_slice(), &[high, low]);
577                let (h, l) = pair.to_typed_code_units();
578                assert_eq!((h.to_u16(), l.to_u16()), (high, low));
579                if let Some((previous_pair, previous_char)) = previous {
580                    // `Ord` is consistent with scalar value order.
581                    assert!(previous_pair < pair);
582                    assert!(previous_char < c);
583                }
584                previous = Some((pair, c));
585            }
586        }
587        assert_eq!(previous.unwrap().1, char::MAX);
588    }
589
590    #[test]
591    fn test_niche() {
592        // No niche for `Bmp` for now!
593        assert_ne!(
594            core::mem::size_of::<Option<Bmp>>(),
595            core::mem::size_of::<Bmp>()
596        );
597        assert_eq!(
598            core::mem::size_of::<Option<Surrogate>>(),
599            core::mem::size_of::<Surrogate>()
600        );
601        assert_eq!(
602            core::mem::size_of::<Option<HighSurrogate>>(),
603            core::mem::size_of::<HighSurrogate>()
604        );
605        assert_eq!(
606            core::mem::size_of::<Option<LowSurrogate>>(),
607            core::mem::size_of::<LowSurrogate>()
608        );
609        assert_eq!(
610            core::mem::size_of::<Option<SurrogatePair>>(),
611            core::mem::size_of::<SurrogatePair>()
612        );
613    }
614}