mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 02:00:51 +00:00
Add JsString <-> char conversions
These are pretty common and already supported via ABI conversions, yet pretty easy to get wrong when converting them manually. Fixes #1363.
This commit is contained in:
parent
ac7230b678
commit
bc4a98d146
@ -3641,6 +3641,36 @@ impl JsString {
|
||||
) -> impl ExactSizeIterator<Item = u16> + DoubleEndedIterator<Item = u16> + 'a {
|
||||
(0..self.length()).map(move |i| self.char_code_at(i) as u16)
|
||||
}
|
||||
|
||||
/// If this string consists of a single Unicode code point, then this method
|
||||
/// converts it into a Rust `char` without doing any allocations.
|
||||
///
|
||||
/// If this JS value is not a valid UTF-8 or consists of more than a single
|
||||
/// codepoint, then this returns `None`.
|
||||
///
|
||||
/// Note that a single Unicode code point might be represented as more than
|
||||
/// one code unit on the JavaScript side. For example, a JavaScript string
|
||||
/// `"\uD801\uDC37"` is actually a single Unicode code point U+10437 which
|
||||
/// corresponds to a character '𐐷'.
|
||||
pub fn as_char(&self) -> Option<char> {
|
||||
let len = self.length();
|
||||
|
||||
if len == 0 || len > 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// This will be simplified when definitions are fixed:
|
||||
// https://github.com/rustwasm/wasm-bindgen/issues/1362
|
||||
let cp = self.code_point_at(0).as_f64().unwrap_throw() as u32;
|
||||
|
||||
let c = std::char::from_u32(cp)?;
|
||||
|
||||
if c.len_utf16() as u32 == len {
|
||||
Some(c)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for JsString {
|
||||
@ -3649,6 +3679,12 @@ impl PartialEq<str> for JsString {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<char> for JsString {
|
||||
fn eq(&self, other: &char) -> bool {
|
||||
self.as_char() == Some(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for JsString {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
<JsString as PartialEq<str>>::eq(self, other)
|
||||
@ -3679,6 +3715,13 @@ impl From<String> for JsString {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for JsString {
|
||||
#[inline]
|
||||
fn from(c: char) -> Self {
|
||||
JsString::from_code_point1(c as u32).unwrap_throw()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a JsString> for String {
|
||||
fn from(s: &'a JsString) -> Self {
|
||||
s.obj.as_string().unwrap_throw()
|
||||
|
@ -553,3 +553,14 @@ fn is_valid_utf16() {
|
||||
assert!(!JsString::from_char_code1(0xd800).is_valid_utf16());
|
||||
assert!(!JsString::from_char_code1(0xdc00).is_valid_utf16());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn as_char() {
|
||||
assert_eq!(JsString::from('a').as_char(), Some('a'));
|
||||
assert_eq!(JsString::from('🥑').as_char(), Some('🥑'));
|
||||
assert_eq!(JsString::from("").as_char(), None);
|
||||
assert_eq!(JsString::from("ab").as_char(), None);
|
||||
assert_eq!(JsString::from_char_code1(0xd800).as_char(), None);
|
||||
assert_eq!(JsString::from_char_code1(0xdc00).as_char(), None);
|
||||
assert_eq!(JsString::from_char_code1(0xdfff).as_char(), None);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user