Skip to content

Commit

Permalink
Make Utf16Char::from_tuple() and ::from_tuple_unchecked() const fn
Browse files Browse the repository at this point in the history
  • Loading branch information
tormol committed Aug 6, 2022
1 parent 801cc1e commit c0593e9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
17 changes: 6 additions & 11 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,17 +526,12 @@ impl CharExt for char {
}
}
fn from_utf16_tuple(utf16: (u16, Option<u16>)) -> Result<Self, InvalidUtf16Tuple> {
use crate::errors::InvalidUtf16Tuple::*;
unsafe{ match utf16 {
(0x00_00..=0xd7_ff, None) | // single
(0xe0_00..=0xff_ff, None) | // single
(0xd8_00..=0xdb_ff, Some(0xdc_00..=0xdf_ff)) // correct surrogate
=> Ok(char::from_utf16_tuple_unchecked(utf16)),
(0xd8_00..=0xdb_ff, Some(_)) => Err(SecondIsNotTrailingSurrogate),
(0xd8_00..=0xdb_ff, None ) => Err(MissingSecond),
(0xdc_00..=0xdf_ff, _ ) => Err(FirstIsTrailingSurrogate),
( _ , Some(_)) => Err(SuperfluousSecond),
}}
unsafe {
match Utf16Char::validate_tuple(utf16) {
Ok(()) => Ok(Self::from_utf16_tuple_unchecked(utf16)),
Err(e) => Err(e),
}
}
}

fn from_utf16_array_unchecked(utf16: [u16;2]) -> Self {
Expand Down
32 changes: 26 additions & 6 deletions src/utf16_char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,27 @@ impl Utf16Char {
pub const unsafe fn from_array_unchecked(units: [u16; 2]) -> Self {
Utf16Char { units }
}
pub(crate) const fn validate_tuple(utf16: (u16,Option<u16>)) -> Result<(),InvalidUtf16Tuple> {
use crate::errors::InvalidUtf16Tuple::*;
match utf16 {
(0x00_00..=0xd7_ff, None) | // single
(0xe0_00..=0xff_ff, None) | // single
(0xd8_00..=0xdb_ff, Some(0xdc_00..=0xdf_ff)) // correct surrogate
=> Ok(()),
(0xd8_00..=0xdb_ff, Some(_)) => Err(SecondIsNotTrailingSurrogate),
(0xd8_00..=0xdb_ff, None ) => Err(MissingSecond),
(0xdc_00..=0xdf_ff, _ ) => Err(FirstIsTrailingSurrogate),
( _ , Some(_)) => Err(SuperfluousSecond),
}
}
/// Validate and store a UTF-16 pair as returned from `char.to_utf16_tuple()`.
pub fn from_tuple(utf16: (u16,Option<u16>)) -> Result<Self,InvalidUtf16Tuple> {
unsafe {char::from_utf16_tuple(utf16).map(|_|
Self::from_tuple_unchecked(utf16)
)}
pub const fn from_tuple(utf16: (u16,Option<u16>)) -> Result<Self,InvalidUtf16Tuple> {
unsafe {
match Self::validate_tuple(utf16) {
Ok(()) => Ok(Self::from_tuple_unchecked(utf16)),
Err(e) => Err(e),
}
}
}
/// Create an `Utf16Char` from a tuple as returned from `char.to_utf16_tuple()`.
///
Expand All @@ -526,8 +542,12 @@ impl Utf16Char {
/// The units must form a valid codepoint with the second being 0 when a
/// surrogate pair is not required.
/// Violating this can easily lead to undefined behavior.
pub unsafe fn from_tuple_unchecked(utf16: (u16,Option<u16>)) -> Self {
Utf16Char { units: [utf16.0, utf16.1.unwrap_or(0)] }
pub const unsafe fn from_tuple_unchecked(utf16: (u16,Option<u16>)) -> Self {
let second = match utf16.1 {
Some(extra) => extra,
None => 0,
};
Utf16Char { units: [utf16.0, second] }
}
/// Create an `Utf16Char` from a single unit.
///
Expand Down

0 comments on commit c0593e9

Please sign in to comment.