Skip to content

Commit

Permalink
Merge pull request #1473 from RReverser/chars
Browse files Browse the repository at this point in the history
Add JsString <-> char conversions
  • Loading branch information
alexcrichton committed Apr 24, 2019
2 parents ac7230b + 680a6bb commit cc89109
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
37 changes: 37 additions & 0 deletions crates/js-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -3679,6 +3709,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()
Expand Down
11 changes: 11 additions & 0 deletions crates/js-sys/tests/wasm/JsString.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit cc89109

Please sign in to comment.