do_not_use_testing_rosidl_runtime_rs/
string.rs1use std::cmp::Ordering;
2use std::ffi::CStr;
3use std::fmt::{self, Debug, Display};
4use std::hash::{Hash, Hasher};
5use std::ops::{Deref, DerefMut};
6
7#[cfg(feature = "serde")]
8mod serde;
9
10use crate::sequence::Sequence;
11use crate::traits::SequenceAlloc;
12
13#[repr(C)]
29pub struct String {
30 data: *mut std::os::raw::c_char,
33 size: usize,
34 capacity: usize,
35}
36
37#[repr(C)]
52pub struct WString {
53 data: *mut std::os::raw::c_ushort,
54 size: usize,
55 capacity: usize,
56}
57
58#[derive(Clone, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
75#[repr(transparent)]
76pub struct BoundedString<const N: usize> {
77 inner: String,
78}
79
80#[derive(Clone, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
97#[repr(transparent)]
98pub struct BoundedWString<const N: usize> {
99 inner: WString,
100}
101
102#[derive(Debug)]
104pub struct StringExceedsBoundsError {
105 pub len: usize,
107 pub upper_bound: usize,
109}
110
111macro_rules! string_impl {
115 ($string:ty, $char_type:ty, $unsigned_char_type:ty, $string_conversion_func:ident, $init:ident, $fini:ident, $assignn:ident, $sequence_init:ident, $sequence_fini:ident, $sequence_copy:ident) => {
116 #[link(name = "rosidl_runtime_c")]
117 extern "C" {
118 fn $init(s: *mut $string) -> bool;
119 fn $fini(s: *mut $string);
120 fn $assignn(s: *mut $string, value: *const $char_type, n: usize) -> bool;
121 fn $sequence_init(seq: *mut Sequence<$string>, size: usize) -> bool;
122 fn $sequence_fini(seq: *mut Sequence<$string>);
123 fn $sequence_copy(
124 in_seq: *const Sequence<$string>,
125 out_seq: *mut Sequence<$string>,
126 ) -> bool;
127 }
128
129 impl Clone for $string {
130 fn clone(&self) -> Self {
131 let mut msg = Self::default();
132 if !unsafe { $assignn(&mut msg as *mut _, self.data as *const _, self.size) } {
134 panic!("$assignn failed");
135 }
136 msg
137 }
138 }
139
140 impl Debug for $string {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
142 Debug::fmt(&self.to_string(), f)
143 }
144 }
145
146 impl Default for $string {
147 fn default() -> Self {
148 let mut msg = Self {
149 data: std::ptr::null_mut(),
150 size: 0,
151 capacity: 0,
152 };
153 if !unsafe { $init(&mut msg as *mut _) } {
155 panic!("$init failed");
156 }
157 msg
158 }
159 }
160
161 impl Deref for $string {
164 type Target = [$char_type];
165 fn deref(&self) -> &Self::Target {
166 unsafe { std::slice::from_raw_parts(self.data, self.size) }
169 }
170 }
171
172 impl DerefMut for $string {
173 fn deref_mut(&mut self) -> &mut Self::Target {
174 unsafe { std::slice::from_raw_parts_mut(self.data, self.size) }
177 }
178 }
179
180 impl Display for $string {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
182 let u8_slice = unsafe {
185 std::slice::from_raw_parts(self.data as *mut $unsigned_char_type, self.size)
186 };
187 let converted = std::string::String::$string_conversion_func(u8_slice);
188 Display::fmt(&converted, f)
189 }
190 }
191
192 impl Drop for $string {
193 fn drop(&mut self) {
194 unsafe {
196 $fini(self as *mut _);
197 }
198 }
199 }
200
201 impl Eq for $string {}
202
203 impl Extend<char> for $string {
204 fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
205 let mut s = self.to_string();
206 s.extend(iter);
207 *self = Self::from(s.as_str());
208 }
209 }
210
211 impl<'a> Extend<&'a char> for $string {
212 fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
213 self.extend(iter.into_iter().cloned());
214 }
215 }
216
217 impl FromIterator<char> for $string {
218 fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
219 let mut buf = <$string>::default();
220 buf.extend(iter);
221 buf
222 }
223 }
224
225 impl<'a> FromIterator<&'a char> for $string {
226 fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> Self {
227 let mut buf = <$string>::default();
228 buf.extend(iter);
229 buf
230 }
231 }
232
233 impl Hash for $string {
234 fn hash<H: Hasher>(&self, state: &mut H) {
235 self.deref().hash(state)
236 }
237 }
238
239 impl Ord for $string {
240 fn cmp(&self, other: &Self) -> Ordering {
241 self.deref().cmp(other.deref())
242 }
243 }
244
245 impl PartialEq for $string {
246 fn eq(&self, other: &Self) -> bool {
247 self.deref().eq(other.deref())
248 }
249 }
250
251 impl PartialOrd for $string {
252 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
253 self.deref().partial_cmp(other.deref())
254 }
255 }
256
257 unsafe impl Send for $string {}
259 unsafe impl Sync for $string {}
261
262 impl SequenceAlloc for $string {
263 fn sequence_init(seq: &mut Sequence<Self>, size: usize) -> bool {
264 unsafe { $sequence_init(seq as *mut _, size) }
266 }
267 fn sequence_fini(seq: &mut Sequence<Self>) {
268 unsafe { $sequence_fini(seq as *mut _) }
270 }
271 fn sequence_copy(in_seq: &Sequence<Self>, out_seq: &mut Sequence<Self>) -> bool {
272 unsafe { $sequence_copy(in_seq as *const _, out_seq as *mut _) }
274 }
275 }
276 };
277}
278
279string_impl!(
280 String,
281 std::os::raw::c_char,
282 u8,
283 from_utf8_lossy,
284 rosidl_runtime_c__String__init,
285 rosidl_runtime_c__String__fini,
286 rosidl_runtime_c__String__assignn,
287 rosidl_runtime_c__String__Sequence__init,
288 rosidl_runtime_c__String__Sequence__fini,
289 rosidl_runtime_c__String__Sequence__copy
290);
291string_impl!(
292 WString,
293 std::os::raw::c_ushort,
294 u16,
295 from_utf16_lossy,
296 rosidl_runtime_c__U16String__init,
297 rosidl_runtime_c__U16String__fini,
298 rosidl_runtime_c__U16String__assignn,
299 rosidl_runtime_c__U16String__Sequence__init,
300 rosidl_runtime_c__U16String__Sequence__fini,
301 rosidl_runtime_c__U16String__Sequence__copy
302);
303
304impl From<&str> for String {
305 fn from(s: &str) -> Self {
306 let mut msg = Self {
307 data: std::ptr::null_mut(),
308 size: 0,
309 capacity: 0,
310 };
311 if !unsafe {
314 rosidl_runtime_c__String__assignn(&mut msg as *mut _, s.as_ptr() as *const _, s.len())
315 } {
316 panic!("rosidl_runtime_c__String__assignn failed");
317 }
318 msg
319 }
320}
321
322impl String {
323 pub fn to_cstr(&self) -> &CStr {
328 unsafe { CStr::from_ptr(self.data as *const _) }
331 }
332}
333
334impl From<&str> for WString {
335 fn from(s: &str) -> Self {
336 let mut msg = Self {
337 data: std::ptr::null_mut(),
338 size: 0,
339 capacity: 0,
340 };
341 let buf: Vec<u16> = s.encode_utf16().collect();
342 if !unsafe {
345 rosidl_runtime_c__U16String__assignn(
346 &mut msg as *mut _,
347 buf.as_ptr() as *const _,
348 buf.len(),
349 )
350 } {
351 panic!("rosidl_runtime_c__U16String__assignn failed");
352 }
353 msg
354 }
355}
356
357impl<const N: usize> Debug for BoundedString<N> {
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
361 Debug::fmt(&self.inner, f)
362 }
363}
364
365impl<const N: usize> Deref for BoundedString<N> {
366 type Target = [std::os::raw::c_char];
367 fn deref(&self) -> &Self::Target {
368 self.inner.deref()
369 }
370}
371
372impl<const N: usize> DerefMut for BoundedString<N> {
373 fn deref_mut(&mut self) -> &mut Self::Target {
374 self.inner.deref_mut()
375 }
376}
377
378impl<const N: usize> Display for BoundedString<N> {
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
380 Display::fmt(&self.inner, f)
381 }
382}
383
384impl<const N: usize> SequenceAlloc for BoundedString<N> {
385 fn sequence_init(seq: &mut Sequence<Self>, size: usize) -> bool {
386 unsafe {
388 rosidl_runtime_c__String__Sequence__init(seq as *mut Sequence<Self> as *mut _, size)
389 }
390 }
391 fn sequence_fini(seq: &mut Sequence<Self>) {
392 unsafe { rosidl_runtime_c__String__Sequence__fini(seq as *mut Sequence<Self> as *mut _) }
394 }
395 fn sequence_copy(in_seq: &Sequence<Self>, out_seq: &mut Sequence<Self>) -> bool {
396 unsafe {
398 <String as SequenceAlloc>::sequence_copy(
399 std::mem::transmute::<&Sequence<Self>, &Sequence<String>>(in_seq),
400 std::mem::transmute::<&mut Sequence<Self>, &mut Sequence<String>>(out_seq),
401 )
402 }
403 }
404}
405
406impl<const N: usize> TryFrom<&str> for BoundedString<N> {
407 type Error = StringExceedsBoundsError;
408 fn try_from(s: &str) -> Result<Self, Self::Error> {
409 let length = s.chars().count();
410 if length <= N {
411 Ok(Self {
412 inner: String::from(s),
413 })
414 } else {
415 Err(StringExceedsBoundsError {
416 len: length,
417 upper_bound: N,
418 })
419 }
420 }
421}
422
423impl<const N: usize> Debug for BoundedWString<N> {
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
427 Debug::fmt(&self.inner, f)
428 }
429}
430
431impl<const N: usize> Deref for BoundedWString<N> {
432 type Target = [u16];
433 fn deref(&self) -> &Self::Target {
434 self.inner.deref()
435 }
436}
437
438impl<const N: usize> DerefMut for BoundedWString<N> {
439 fn deref_mut(&mut self) -> &mut Self::Target {
440 self.inner.deref_mut()
441 }
442}
443
444impl<const N: usize> Display for BoundedWString<N> {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
446 Display::fmt(&self.inner, f)
447 }
448}
449
450impl<const N: usize> SequenceAlloc for BoundedWString<N> {
451 fn sequence_init(seq: &mut Sequence<Self>, size: usize) -> bool {
452 unsafe {
454 rosidl_runtime_c__U16String__Sequence__init(seq as *mut Sequence<Self> as *mut _, size)
455 }
456 }
457 fn sequence_fini(seq: &mut Sequence<Self>) {
458 unsafe { rosidl_runtime_c__U16String__Sequence__fini(seq as *mut Sequence<Self> as *mut _) }
460 }
461 fn sequence_copy(in_seq: &Sequence<Self>, out_seq: &mut Sequence<Self>) -> bool {
462 unsafe {
464 <WString as SequenceAlloc>::sequence_copy(
465 std::mem::transmute::<&Sequence<Self>, &Sequence<WString>>(in_seq),
466 std::mem::transmute::<&mut Sequence<Self>, &mut Sequence<WString>>(out_seq),
467 )
468 }
469 }
470}
471
472impl<const N: usize> TryFrom<&str> for BoundedWString<N> {
473 type Error = StringExceedsBoundsError;
474 fn try_from(s: &str) -> Result<Self, Self::Error> {
475 let length = s.chars().count();
476 if length <= N {
477 Ok(Self {
478 inner: WString::from(s),
479 })
480 } else {
481 Err(StringExceedsBoundsError {
482 len: length,
483 upper_bound: N,
484 })
485 }
486 }
487}
488
489impl Display for StringExceedsBoundsError {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
493 write!(
494 f,
495 "BoundedString with upper bound {} initialized with len {}",
496 self.upper_bound, self.len
497 )
498 }
499}
500
501impl std::error::Error for StringExceedsBoundsError {}
502
503#[cfg(test)]
504mod tests {
505 use quickcheck::{Arbitrary, Gen};
506
507 use super::*;
508
509 impl Arbitrary for String {
510 fn arbitrary(g: &mut Gen) -> Self {
511 std::string::String::arbitrary(g).as_str().into()
512 }
513 }
514
515 impl Arbitrary for WString {
516 fn arbitrary(g: &mut Gen) -> Self {
517 std::string::String::arbitrary(g).as_str().into()
518 }
519 }
520
521 impl Arbitrary for BoundedString<256> {
522 fn arbitrary(g: &mut Gen) -> Self {
523 let len = u8::arbitrary(g);
524 let s: std::string::String = (0..len).map(|_| char::arbitrary(g)).collect();
525 s.as_str().try_into().unwrap()
526 }
527 }
528
529 impl Arbitrary for BoundedWString<256> {
530 fn arbitrary(g: &mut Gen) -> Self {
531 let len = u8::arbitrary(g);
532 let s: std::string::String = (0..len).map(|_| char::arbitrary(g)).collect();
533 s.as_str().try_into().unwrap()
534 }
535 }
536
537 #[test]
538 fn string_from_char_iterator() {
539 let expected = String::from("abc");
541 let actual = "abc".chars().collect::<String>();
542
543 assert_eq!(expected, actual);
544
545 let expected = String::from("");
547 let actual = "".chars().collect::<String>();
548
549 assert_eq!(expected, actual);
550
551 let expected = String::from("Grüß Gott! 𝕊");
553 let actual = "Grüß Gott! 𝕊".chars().collect::<String>();
554
555 assert_eq!(expected, actual);
556 }
557
558 #[test]
559 fn extend_string_with_char_iterator() {
560 let expected = WString::from("abcdef");
561 let mut actual = WString::from("abc");
562 actual.extend("def".chars());
563
564 assert_eq!(expected, actual);
565 }
566
567 #[test]
568 fn wstring_from_char_iterator() {
569 let expected = WString::from("abc");
571 let actual = "abc".chars().collect::<WString>();
572
573 assert_eq!(expected, actual);
574
575 let expected = WString::from("");
577 let actual = "".chars().collect::<WString>();
578
579 assert_eq!(expected, actual);
580
581 let expected = WString::from("Grüß Gott! 𝕊");
583 let actual = "Grüß Gott! 𝕊".chars().collect::<WString>();
584
585 assert_eq!(expected, actual);
586 }
587
588 #[test]
589 fn extend_wstring_with_char_iterator() {
590 let expected = WString::from("abcdef");
591 let mut actual = WString::from("abc");
592 actual.extend("def".chars());
593
594 assert_eq!(expected, actual);
595 }
596}