Skip to main content

hicc_std/
std_string.rs

1use std::cmp::min;
2use std::cmp::{Ordering, PartialEq, PartialOrd};
3use std::convert::From;
4use std::ffi::CStr;
5use std::slice;
6
7hicc::cpp! {
8    #include <string>
9}
10
11hicc::import_class! {
12    #[cpp(class = "template<class CharT, class Traits, class Allocator> std::basic_string<CharT, Traits, Allocator>")]
13    pub class basic_string<CharT> {
14        pub const npos: usize = usize::MAX;
15        /// ```
16        /// use std::ffi::CStr;
17        /// use hicc_std::string;
18        /// let s = string::from(hicc::cstr!("abc"));
19        /// let cstr = unsafe { CStr::from_ptr(s.c_str()) };
20        /// assert_eq!(cstr, hicc::cstr!("abc"));
21        /// ```
22        #[cpp(method = "const CharT* c_str() const")]
23        pub fn c_str(&self) -> *const CharT;
24
25        /// ```
26        /// use hicc_std::string;
27        /// let s = string::new();
28        /// assert!(s.is_empty());
29        /// ```
30        #[cpp(method = "bool empty() const")]
31        pub fn is_empty(&self) -> bool;
32
33        /// ```
34        /// use hicc_std::string;
35        /// let s = string::new();
36        /// assert_eq!(s.size(), 0);
37        /// ```
38        #[cpp(method = "size_t size() const")]
39        pub fn size(&self) -> usize;
40
41        /// ```
42        /// use hicc_std::string;
43        /// let s = string::new();
44        /// println!("s.max_size = {}", s.max_size());
45        /// ```
46        #[cpp(method = "size_t max_size() const")]
47        pub fn max_size(&self) -> usize;
48
49        /// ```
50        /// use hicc_std::string;
51        /// let s = string::new();
52        /// println!("s.capacity = {}", s.capacity());
53        /// ```
54        #[cpp(method = "size_t capacity() const")]
55        pub fn capacity(&self) -> usize;
56
57        /// ```
58        /// use hicc_std::string;
59        /// let mut s = string::from(hicc::cstr!("a"));
60        /// s.resize(3, b'c' as i8);
61        /// assert_eq!(s.as_cstr(), hicc::cstr!("acc"));
62        /// ```
63        #[cpp(method = "void resize(size_t, CharT) ")]
64        pub fn resize(&mut self, n: usize, c: CharT);
65
66        /// ```
67        /// use hicc_std::string;
68        /// let mut s = string::from(hicc::cstr!("abc"));
69        /// s.reserve(100);
70        /// println!("s.capacity = {}", s.capacity());
71        /// ```
72        #[cpp(method = "void reserve(size_t)")]
73        pub fn reserve(&mut self, n: usize);
74
75        /// ```
76        /// use hicc_std::string;
77        /// let mut s = string::from(hicc::cstr!("abc"));
78        /// s.clear();
79        /// assert!(s.is_empty());
80        /// ```
81        #[cpp(method = "void clear()")]
82        pub fn clear(&mut self);
83
84        /// ```
85        /// use hicc_std::string;
86        /// let mut s = string::from(hicc::cstr!("abc"));
87        /// s.reserve(100);
88        /// println!("before shrink_to_fit: capacity = {}", s.capacity());
89        /// s.assign(10, b'c' as i8);
90        /// s.shrink_to_fit();
91        /// println!("after shrink_to_fit: capacity = {}", s.capacity());
92        /// ```
93        #[cpp(method = "void shrink_to_fit()")]
94        pub fn shrink_to_fit(&mut self);
95
96        /// 如果pos超出范围,会返回空字符串.
97        /// ```
98        /// use hicc_std::string;
99        /// let mut s = string::from(hicc::cstr!("abc"));
100        /// let substr = s.substr(1, 2);
101        /// assert_eq!(substr.as_cstr(), hicc::cstr!("bc"));
102        /// ```
103        pub fn substr(&self, mut pos: usize, len: usize) -> Self {
104            if pos > self.size() {
105                pos = self.size();
106            }
107            self._substr(pos, len)
108        }
109        #[cpp(method = "Self substr(size_t, size_t) const")]
110        fn _substr(&self, pos: usize, len: usize) -> Self;
111
112        /// ```
113        /// use hicc_std::string;
114        /// let s1 = string::from(hicc::cstr!("abc"));
115        /// let s2 = string::from(hicc::cstr!("abd"));
116        /// assert!(s1 < s2);
117        /// assert!(s1 != s2);
118        /// ```
119        #[cpp(method = "int compare(const Self&) const")]
120        pub fn compare(&self, other: &Self) -> i32;
121
122        /// ```
123        /// use hicc_std::string;
124        /// let s1 = string::from(hicc::cstr!("abcdef"));
125        /// let s2 = string::from(hicc::cstr!("bcd"));
126        /// assert_eq!(s1.find_str(&s2, 0), 1);
127        /// ```
128        #[cpp(method = "size_t find(const Self&, size_t) const")]
129        pub fn find_str(&self, target: &Self, pos: usize) -> usize;
130
131        /// ```
132        /// use hicc_std::string;
133        /// let s = string::from(hicc::cstr!("abcdef"));
134        /// assert_eq!(s.find(b'c' as i8, 1), 2);
135        /// ```
136        #[cpp(method = "size_t find(CharT, size_t) const")]
137        pub fn find(&self, c: CharT, pos: usize) -> usize;
138
139        /// ```
140        /// use hicc_std::string;
141        /// let s1 = string::from(hicc::cstr!("abcdef"));
142        /// let s2 = string::from(hicc::cstr!("bcd"));
143        /// assert_eq!(s1.rfind_str(&s2, string::npos), 1);
144        /// ```
145        #[cpp(method = "size_t rfind(const Self&, size_t) const")]
146        pub fn rfind_str(&self, target: &Self, pos: usize) -> usize;
147
148        /// ```
149        /// use hicc_std::string;
150        /// let s = string::from(hicc::cstr!("abcdef"));
151        /// assert_eq!(s.rfind(b'c' as i8, string::npos), 2);
152        /// ```
153        #[cpp(method = "size_t rfind(CharT, size_t) const")]
154        pub fn rfind(&self, c: CharT, pos: usize) -> usize;
155
156        /// ```
157        /// use hicc_std::string;
158        /// let s1 = string::from(hicc::cstr!("abcdef"));
159        /// let s2 = string::from(hicc::cstr!("dfb"));
160        /// assert_eq!(s1.find_first_of(&s2, 0), 1);
161        /// ```
162        #[cpp(method = "size_t find_first_of(const Self&, size_t) const")]
163        pub fn find_first_of(&self, target: &Self, pos: usize) -> usize;
164
165        /// ```
166        /// use hicc_std::string;
167        /// let s = string::from(hicc::cstr!("abcabc"));
168        /// assert_eq!(s.find_first(b'c' as i8, 0), 2);
169        /// ```
170        #[cpp(method = "size_t find_first_of(CharT, size_t) const")]
171        pub fn find_first(&self, c: CharT, pos: usize) -> usize;
172
173        /// ```
174        /// use hicc_std::string;
175        /// let s1 = string::from(hicc::cstr!("abcdef"));
176        /// let s2 = string::from(hicc::cstr!("dfb"));
177        /// assert_eq!(s1.find_last_of(&s2, string::npos), 5);
178        /// ```
179        #[cpp(method = "size_t find_last_of(const Self&, size_t) const")]
180        pub fn find_last_of(&self, target: &Self, pos: usize) -> usize;
181
182        /// ```
183        /// use hicc_std::string;
184        /// let s = string::from(hicc::cstr!("abcabc"));
185        /// assert_eq!(s.find_last(b'c' as i8, string::npos), 5);
186        /// ```
187        #[cpp(method = "size_t find_last_of(CharT, size_t) const")]
188        pub fn find_last(&self, c: CharT, pos: usize) -> usize;
189
190        /// ```
191        /// use hicc_std::string;
192        /// let s1 = string::from(hicc::cstr!("abcdef"));
193        /// let s2 = string::from(hicc::cstr!("abc"));
194        /// assert_eq!(s1.find_first_not_of(&s2, 0), 3);
195        /// ```
196        #[cpp(method = "size_t find_first_not_of(const Self&, size_t) const")]
197        pub fn find_first_not_of(&self, target: &Self, pos: usize) -> usize;
198
199        /// ```
200        /// use hicc_std::string;
201        /// let s = string::from(hicc::cstr!("abcabc"));
202        /// assert_eq!(s.find_first_not(b'a' as i8, 0), 1);
203        /// ```
204        #[cpp(method = "size_t find_first_not_of(CharT, size_t) const")]
205        pub fn find_first_not(&self, c: CharT, pos: usize) -> usize;
206
207        /// ```
208        /// use hicc_std::string;
209        /// let s1 = string::from(hicc::cstr!("abcdef"));
210        /// let s2 = string::from(hicc::cstr!("def"));
211        /// assert_eq!(s1.find_last_not_of(&s2, string::npos), 2);
212        /// ```
213        #[cpp(method = "size_t find_last_not_of(const Self&, size_t) const")]
214        pub fn find_last_not_of(&self, target: &Self, pos: usize) -> usize;
215
216        /// ```
217        /// use hicc_std::string;
218        /// let s = string::from(hicc::cstr!("abcabc"));
219        /// assert_eq!(s.find_last_not(b'c' as i8, string::npos), 4);
220        /// ```
221        #[cpp(method = "size_t find_last_not_of(CharT, size_t) const")]
222        pub fn find_last_not(&self, c: CharT, pos: usize) -> usize;
223
224        /// 如果subpos超出范围则不做任何改变.
225        /// ```
226        /// use hicc_std::string;
227        /// let mut s1 = string::from(hicc::cstr!("abc"));
228        /// let s2 = string::from(hicc::cstr!("def"));
229        /// s1.append_str(&s2, 0, 2);
230        /// assert_eq!(s1.as_cstr(), hicc::cstr!("abcde"));
231        /// ```
232        pub fn append_str(&mut self, s: &Self, subpos: usize, sublen: usize) {
233            if subpos < s.size() {
234                self._append_str(s, subpos, sublen);
235            }
236        }
237        #[cpp(method = "Self& append(const Self&, size_t, size_t)")]
238        fn _append_str(&mut self, s: &Self, subpos: usize, sublen: usize);
239
240        /// ```
241        /// use hicc_std::string;
242        /// let mut s = string::from(hicc::cstr!("abc"));
243        /// s.append(1, b'd' as i8);
244        /// assert_eq!(s.as_cstr(), hicc::cstr!("abcd"));
245        /// ```
246        #[cpp(method = "Self& append(size_t, CharT)")]
247        pub fn append(&mut self, n: usize, c: CharT);
248
249        /// 如果subpos超出范围不做任何改变, 如果pos超出范围则追加到最后.
250        /// ```
251        /// use hicc_std::string;
252        /// let mut s1 = string::from(hicc::cstr!("abc"));
253        /// let mut s2 = string::from(hicc::cstr!("def"));
254        /// s1.insert_str(0, &s2, 0, string::npos);
255        /// assert_eq!(s1.as_cstr(), hicc::cstr!("defabc"));
256        /// s1.insert_str(100, &s2, 0, string::npos);
257        /// assert_eq!(s1.as_cstr(), hicc::cstr!("defabcdef"));
258        /// ```
259        pub fn insert_str(&mut self, pos: usize, s: &Self, subpos: usize, sublen: usize) {
260            if subpos < s.size() {
261                self._insert_str(min(pos, self.size()), s, subpos, sublen);
262            }
263        }
264        #[cpp(method = "Self& insert(size_t, const Self&, size_t, size_t)")]
265        fn _insert_str(&mut self, pos: usize, s: &Self, subpos: usize, sublen: usize);
266
267        /// 如果pos超出范围则追加到最后.
268        /// ```
269        /// use hicc_std::string;
270        /// let mut s = string::from(hicc::cstr!("abc"));
271        /// s.insert(0, 3, b'd' as i8);
272        /// assert_eq!(s.as_cstr(), hicc::cstr!("dddabc"));
273        /// s.insert(110, 3, b'd' as i8);
274        /// assert_eq!(s.as_cstr(), hicc::cstr!("dddabcddd"));
275        /// ```
276        pub fn insert(&mut self, pos: usize, n: usize, c: CharT::InputType) {
277            self._insert(min(pos, self.size()), n, c);
278        }
279        #[cpp(method = "Self& insert(size_t, size_t, CharT)")]
280        fn _insert(&mut self, pos: usize, n: usize, c: CharT);
281
282        /// 如果pos或者subpos超出范围则不做任何改变.
283        /// ```
284        /// use hicc_std::string;
285        /// let mut s1 = string::from(hicc::cstr!("abc"));
286        /// let mut s2 = string::from(hicc::cstr!("de"));
287        /// s1.replace_str(0, string::npos, &s2, 0, string::npos);
288        /// assert_eq!(s1.as_cstr(), hicc::cstr!("de"));
289        /// ```
290        pub fn replace_str(&mut self, pos: usize, len: usize, s: &Self, subpos: usize, sublen: usize) {
291            if pos < self.size() && subpos < s.size() {
292                self._replace_str(pos, len, s, subpos, sublen);
293            }
294        }
295        #[cpp(method = "Self& replace(size_t, size_t, const Self&, size_t, size_t)")]
296        fn _replace_str(&mut self, pos: usize, len: usize, s: &Self, subpos: usize, sublen: usize);
297
298        /// 如果pos超出范围则不做任何改变.
299        /// ```
300        /// use hicc_std::string;
301        /// let mut s = string::from(hicc::cstr!("abc"));
302        /// s.replace(0, string::npos, 1, b'd' as i8);
303        /// assert_eq!(s.as_cstr(), hicc::cstr!("d"));
304        /// ```
305        pub fn replace(&mut self, pos: usize, len: usize, n: usize, c: CharT::InputType) {
306            if pos < self.size() {
307                self._replace(pos, len, n, c);
308            }
309        }
310        #[cpp(method = "Self& replace(size_t, size_t, size_t, CharT)")]
311        fn _replace(&mut self, pos: usize, len: usize, n: usize, c: CharT);
312
313        /// 如果subpos超出范围则不做任何改变.
314        /// ```
315        /// use hicc_std::string;
316        /// let mut s1 = string::from(hicc::cstr!("abc"));
317        /// let mut s2 = string::from(hicc::cstr!("de"));
318        /// s1.assign_str(&s2, 0, string::npos);
319        /// assert_eq!(s1.as_cstr(), hicc::cstr!("de"));
320        /// ```
321        pub fn assign_str(&mut self, s: &Self, subpos: usize, sublen: usize) {
322            if subpos < s.size() {
323                self._assign_str(s, subpos, sublen);
324            }
325        }
326        #[cpp(method = "Self& assign(const Self&, size_t, size_t)")]
327        fn _assign_str(&mut self, s: &Self, subpos: usize, sublen: usize);
328
329        /// ```
330        /// use hicc_std::string;
331        /// let mut s = string::from(hicc::cstr!("abc"));
332        /// s.assign(1, b'd' as i8);
333        /// assert_eq!(s.as_cstr(), hicc::cstr!("d"));
334        /// ```
335        #[cpp(method = "Self& assign(size_t, CharT)")]
336        pub fn assign(&mut self, n: usize, c: CharT);
337
338        /// 如果pos超出范围则不做任何改变.
339        /// ```
340        /// use hicc_std::string;
341        /// let mut s = string::from(hicc::cstr!("abc"));
342        /// s.erase(1, 1);
343        /// assert_eq!(s.as_cstr(), hicc::cstr!("ac"));
344        /// ```
345        pub fn erase(&mut self, pos: usize, len: usize) {
346            if pos < self.size() {
347                self._erase(pos, len);
348            }
349        }
350        #[cpp(method = "Self& erase(size_t, size_t)")]
351        fn _erase(&mut self, pos: usize, len: usize);
352
353
354        /// ```
355        /// use hicc_std::string;
356        /// let mut s = string::from(hicc::cstr!("abc"));
357        /// s.push_back(b'd' as i8);
358        /// assert_eq!(s.as_cstr(), hicc::cstr!("abcd"));
359        /// ```
360        #[cpp(method = "void push_back(CharT)")]
361        pub fn push_back(&mut self, c: CharT);
362
363        /// 如果为空则不做任何改变.
364        /// ```
365        /// use hicc_std::string;
366        /// let mut s = string::from(hicc::cstr!("abc"));
367        /// s.pop_back();
368        /// assert_eq!(s.as_cstr(), hicc::cstr!("ab"));
369        /// ```
370        pub fn pop_back(&mut self) {
371            if !self.is_empty() {
372                self._pop_back();
373            }
374        }
375        #[cpp(method = "void pop_back()")]
376        fn _pop_back(&mut self);
377
378        /// ```
379        /// use hicc_std::string;
380        /// let mut s1 = string::from(hicc::cstr!("abc"));
381        /// let mut s2 = string::from(hicc::cstr!("de"));
382        /// s1.swap(&mut s2);
383        /// assert_eq!(s1.as_cstr(), hicc::cstr!("de"));
384        /// assert_eq!(s2.as_cstr(), hicc::cstr!("abc"));
385        /// ```
386        #[cpp(method = "void swap(Self&)")]
387        pub fn swap(&mut self, other: &mut Self);
388
389        /// ```
390        /// use hicc_std::string;
391        /// let s = string::from(hicc::cstr!("abc"));
392        /// assert_eq!(s.get(0), Some(&(b'a' as i8)));
393        /// assert_eq!(s.get(3), None);
394        /// ```
395        pub fn get(&self, pos: usize) -> Option<CharT::OutputRef<'_>> {
396            if pos < self.size() {
397                return Some(self._get(pos));
398            }
399            None
400        }
401        #[cpp(method = "const CharT& at(size_t) const")]
402        fn _get(&self, pos: usize) -> &CharT;
403
404
405        /// ```
406        /// use hicc_std::string;
407        /// let mut s = string::from(hicc::cstr!("abc"));
408        /// assert!(s.get_mut(0).is_some());
409        /// assert_eq!(*s.get_mut(0).unwrap(), b'a' as i8);
410        /// assert_eq!(s.get(3), None);
411        /// ```
412        pub fn get_mut(&mut self, pos: usize) -> Option<CharT::OutputRefMut<'_>> {
413            if pos < self.size() {
414                return Some(self._get_mut(pos));
415            }
416            None
417        }
418        #[cpp(method = "CharT& at(size_t)")]
419        fn _get_mut(&mut self, pos: usize) -> &mut CharT;
420    }
421
422    /// 对应`std::string`
423    #[allow(non_camel_case_types)]
424    pub type string = basic_string<hicc::Pod<i8>>;
425    /// 对应`std::u16string`
426    #[allow(non_camel_case_types)]
427    pub type u16string = basic_string<hicc::Pod<i16>>;
428    /// 对应`std::u32string`
429    #[allow(non_camel_case_types)]
430    pub type u32string = basic_string<hicc::Pod<i32>>;
431}
432
433unsafe impl<CharT: hicc::AbiType + Sync> Send for basic_string<CharT> {}
434unsafe impl<CharT: hicc::AbiType + Sync> Sync for basic_string<CharT> {}
435
436impl<T: Sized + 'static> basic_string<hicc::Pod<T>> {
437    /// ```
438    /// use hicc_std::string;
439    /// let mut s = string::with_cstr(hicc::cstr!("bcd"));
440    /// assert_eq!(s.as_slice(), &[b'b' as i8, b'c' as i8, b'd' as i8]);
441    /// ```
442    pub fn as_slice(&self) -> &[T] {
443        let cstr = self.c_str();
444        let size = self.size();
445        unsafe { slice::from_raw_parts(cstr, size) }
446    }
447
448    /// ```
449    /// use hicc_std::string;
450    /// let mut s = string::with_cstr(hicc::cstr!("abc"));
451    /// s.as_slice_mut().iter_mut().for_each(|mut c| { *c += 1; });
452    /// assert_eq!(s.as_slice(), &[b'b' as i8, b'c' as i8, b'd' as i8]);
453    /// ```
454    pub fn as_slice_mut(&mut self) -> &mut [T] {
455        let cstr = self.c_str();
456        let size = self.size();
457        unsafe { slice::from_raw_parts_mut(cstr.cast_mut(), size) }
458    }
459}
460
461impl<T: hicc::AbiType> PartialEq for basic_string<T> {
462    fn eq(&self, other: &Self) -> bool {
463        self.compare(other) == 0
464    }
465}
466
467impl<T: hicc::AbiType> PartialOrd for basic_string<T> {
468    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
469        match self.compare(other) {
470            0 => Some(Ordering::Equal),
471            1.. => Some(Ordering::Greater),
472            _ => Some(Ordering::Less),
473        }
474    }
475}
476
477impl From<&CStr> for string {
478    fn from(s: &CStr) -> Self {
479        Self::with_cstr(s)
480    }
481}
482
483impl Default for string {
484    fn default() -> Self {
485        Self::new()
486    }
487}
488
489impl Default for u16string {
490    fn default() -> Self {
491        Self::new()
492    }
493}
494
495impl Default for u32string {
496    fn default() -> Self {
497        Self::new()
498    }
499}
500
501hicc::import_lib! {
502    #![link_name = "hicc_std_string"]
503
504    class string;
505    class u16string;
506    class u32string;
507
508    impl string {
509        #[cpp(func = "std::unique_ptr<std::string> hicc::make_unique<std::string>()")]
510        pub fn new() -> Self;
511
512        #[cpp(func = "std::unique_ptr<std::string> hicc::make_unique<std::string, const char*>(const char* &&)")]
513        pub fn with_cstr(s: &CStr) -> Self;
514
515        #[cpp(func = "std::unique_ptr<std::string> hicc::make_unique<std::string, const char*, size_t>(const char* &&, size_t&&)")]
516        pub unsafe fn with_cbuf(s: *const u8, len: usize) -> Self;
517
518        pub fn with_buf(b: &[u8]) -> Self {
519            unsafe { Self::with_cbuf(b.as_ptr(), b.len()) }
520        }
521
522        pub fn as_buf(&self) -> &[u8] {
523            unsafe { slice::from_raw_parts(self.c_str() as *const u8, self.size()) }
524        }
525
526        pub fn as_cstr(&self) -> &CStr {
527            unsafe { CStr::from_ptr(self.c_str()) }
528        }
529
530    }
531
532    #[inline(always)]
533    pub fn string_new() -> string {
534        string::new()
535    }
536
537    #[inline(always)]
538    pub fn string_with_cstr(s: *const i8) -> string {
539        let cs: &CStr = unsafe { CStr::from_ptr(s) };
540        string::with_cstr(cs)
541    }
542
543    #[inline(always)]
544    pub unsafe fn string_with_buf(s: *const u8, len: usize) -> string {
545        unsafe { string::with_cbuf(s, len) }
546    }
547
548    impl u16string {
549        #[cpp(func = "std::unique_ptr<std::u16string> hicc::make_unique<std::u16string>()")]
550        pub fn new() -> Self;
551
552        #[cpp(func = "std::unique_ptr<std::u16string> hicc::make_unique<std::u16string, const char16_t*, size_t>(const char16_t* &&, size_t&&)")]
553        pub unsafe fn with_cbuf(s: *const u16, len: usize) -> Self;
554
555        pub fn with_buf(b: &[u16]) -> Self {
556            unsafe { Self::with_cbuf(b.as_ptr(), b.len()) }
557        }
558
559        pub fn as_buf(&self) -> &[u16] {
560            unsafe { slice::from_raw_parts(self.c_str() as *const u16, self.size()) }
561        }
562    }
563
564    #[inline(always)]
565    pub fn u16string_new() -> u16string {
566        u16string::new()
567    }
568
569    #[inline(always)]
570    pub unsafe fn u16string_with_buf(s: *const u16, len: usize) -> u16string {
571        unsafe { u16string::with_cbuf(s, len) }
572    }
573
574    impl u32string {
575        #[cpp(func = "std::unique_ptr<std::u32string> hicc::make_unique<std::u32string>()")]
576        pub fn new() -> Self;
577
578        #[cpp(func = "std::unique_ptr<std::u32string> hicc::make_unique<std::u32string, const char32_t*, size_t>(const char32_t* &&, size_t&&)")]
579        pub unsafe fn with_cbuf(s: *const u32, len: usize) -> Self;
580
581        pub fn with_buf(b: &[u32]) -> Self {
582            unsafe { Self::with_cbuf(b.as_ptr(), b.len()) }
583        }
584
585        pub fn as_buf(&self) -> &[u32] {
586            unsafe { slice::from_raw_parts(self.c_str() as *const u32, self.size()) }
587        }
588    }
589
590    #[inline(always)]
591    pub fn u32string_new() -> u32string {
592        u32string::new()
593    }
594
595    #[inline(always)]
596    pub unsafe fn u32string_with_buf(s: *const u32, len: usize) -> u32string {
597        unsafe { u32string::with_cbuf(s, len) }
598    }
599}