MCPcopy Create free account
hub / github.com/apache/fory / to_utf8

Function to_utf8

rust/fory-core/src/util/string_util.rs:35–108  ·  view source on GitHub ↗

Converts UTF-16 encoded data to UTF-8.

(utf16: &[u16], is_little_endian: bool)

Source from the content-addressed store, hash-verified

33
34/// Converts UTF-16 encoded data to UTF-8.
35pub fn to_utf8(utf16: &[u16], is_little_endian: bool) -> Result<Vec<u8>, String> {
36 // Pre-allocating capacity to avoid dynamic resizing.
37 // Longest case: 1 u16 to 3 u8.
38 let mut utf8_bytes: Vec<u8> = Vec::with_capacity(utf16.len() * 3);
39 let ptr = utf8_bytes.as_mut_ptr();
40 let mut offset = 0;
41 let mut iter = utf16.iter();
42 while let Some(&wc) = iter.next() {
43 let wc = if is_little_endian {
44 swap_endian(wc)
45 } else {
46 wc
47 };
48 match wc {
49 code_point if code_point < 0x80 => {
50 unsafe {
51 ptr.add(offset).write(code_point as u8);
52 }
53 offset += 1;
54 }
55 code_point if code_point < 0x800 => {
56 let bytes = [
57 ((code_point >> 6) & 0b1_1111) as u8 | 0b1100_0000,
58 (code_point & 0b11_1111) as u8 | 0b1000_0000,
59 ];
60 unsafe {
61 ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(offset), 2);
62 }
63 offset += 2;
64 }
65 wc1 if (0xd800..=0xdbff).contains(&wc1) => {
66 if let Some(&wc2) = iter.next() {
67 let wc2 = if is_little_endian {
68 swap_endian(wc2)
69 } else {
70 wc2
71 };
72 if !(0xdc00..=0xdfff).contains(&wc2) {
73 return Err("Invalid UTF-16 string: wrong surrogate pair".to_string());
74 }
75 let code_point =
76 ((((wc1 as u32) - 0xd800) << 10) | ((wc2 as u32) - 0xdc00)) + 0x10000;
77 let bytes = [
78 ((code_point >> 18) & 0b111) as u8 | 0b1111_0000,
79 ((code_point >> 12) & 0b11_1111) as u8 | 0b1000_0000,
80 ((code_point >> 6) & 0b11_1111) as u8 | 0b1000_0000,
81 (code_point & 0b11_1111) as u8 | 0b1000_0000,
82 ];
83 unsafe {
84 ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(offset), 4);
85 }
86 offset += 4;
87 } else {
88 return Err("Invalid UTF-16 string: missing surrogate pair".to_string());
89 }
90 }
91 _ => {
92 let bytes = [

Callers 5

test_to_utf8Function · 0.85
test_to_utf8_3byteFunction · 0.85
test_to_utf8_endianFunction · 0.85

Calls 7

lenMethod · 0.80
swap_endianFunction · 0.70
writeMethod · 0.65
addMethod · 0.65
nextMethod · 0.45
containsMethod · 0.45
to_stringMethod · 0.45

Tested by 5

test_to_utf8Function · 0.68
test_to_utf8_3byteFunction · 0.68
test_to_utf8_endianFunction · 0.68