Skip to main content

nanvm_lib/vm/string/
from_char_code.rs

1use super::String;
2use crate::vm::{Any, Array, IVm, ToString};
3
4impl<A: IVm> String<A> {
5    /// `String.fromCharCode(...args)`: ToUint16 of each argument, in order.
6    /// Code units are preserved, including unpaired surrogates.
7    pub fn from_char_code(args: Array<A>) -> Result<Self, Any<A>> {
8        let units = args
9            .into_iter()
10            .map(|value| value.to_number().map(|number| number.to_uint32() as u16))
11            .collect::<Result<Vec<_>, _>>()?;
12        Ok(units.into_iter().to_string())
13    }
14}
15
16#[cfg(test)]
17mod tests {
18    use crate::{
19        naive::Naive,
20        vm::{Any, String, ToAny, ToArray},
21    };
22
23    #[test]
24    fn code_units_and_coercion() {
25        let args: [Any<Naive>; 8] = [
26            5.0.to_any(),
27            6.0.to_any(),
28            (-1.5).to_any(),
29            (0x1_0041 as f64).to_any(),
30            (0xd800 as f64).to_any(),
31            f64::NAN.to_any(),
32            f64::INFINITY.to_any(),
33            "66".into(),
34        ];
35        let actual = String::from_char_code(args.to_array()).unwrap();
36        assert_eq!(
37            actual.into_iter().collect::<Vec<_>>(),
38            [5, 6, 0xffff, 0x41, 0xd800, 0, 0, 0x42]
39        );
40        assert_eq!(
41            String::<Naive>::from_char_code([].to_array())
42                .unwrap()
43                .into_iter()
44                .count(),
45            0
46        );
47    }
48
49    #[test]
50    fn conversion_failure() {
51        let args: [Any<Naive>; 2] = [65.0.to_any(), crate::vm::BigInt::from(1u64).to_any()];
52        assert!(String::from_char_code(args.to_array()).is_err());
53    }
54}