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}