Skip to main content

oxidros_msg/
strings.rs

1//! Definition of Strings
2use oxidros_core::msg::TryClone;
3
4use std::fmt::Display;
5
6// ============================================================================
7// rcl feature - FFI implementations
8// ============================================================================
9#[cfg(feature = "rcl")]
10mod rcl_impl {
11    use super::*;
12    use crate::rcl::*;
13    use std::{ffi::CString, mem::transmute};
14
15    /// String.
16    /// `N` represents the maximum number of characters excluding `\0`.
17    /// If `N` is `0`, the string is unlimited.
18    #[repr(C)]
19    #[derive(Debug)]
20    pub struct RosString<const N: usize>(rosidl_runtime_c__String);
21
22    impl<const N: usize> RosString<N> {
23        pub fn new(s: &str) -> Option<Self> {
24            let mut msg: rosidl_runtime_c__String = unsafe { std::mem::zeroed() };
25
26            // initialize string
27            if unsafe { rosidl_runtime_c__String__init(&mut msg) } {
28                if Self::assign_string(&mut msg, s) {
29                    Some(Self(msg))
30                } else {
31                    None
32                }
33            } else {
34                None
35            }
36        }
37
38        pub fn null() -> Self {
39            let msg: rosidl_runtime_c__String = unsafe { std::mem::zeroed() };
40            Self(msg)
41        }
42
43        fn assign_string(msg: &mut rosidl_runtime_c__String, s: &str) -> bool {
44            let cs = CString::new(s).unwrap();
45
46            // assign string
47            if N == 0 {
48                unsafe { rosidl_runtime_c__String__assign(msg, cs.as_ptr()) }
49            } else {
50                unsafe { rosidl_runtime_c__String__assignn(msg, cs.as_ptr(), N as _) }
51            }
52        }
53
54        pub fn assign(&mut self, s: &str) -> bool {
55            Self::assign_string(&mut self.0, s)
56        }
57
58        pub fn as_slice(&self) -> &[std::os::raw::c_char] {
59            if self.0.data.is_null() {
60                &[]
61            } else {
62                unsafe { std::slice::from_raw_parts(self.0.data, self.0.size) }
63            }
64        }
65
66        pub fn as_mut_slice(&mut self) -> &mut [std::os::raw::c_char] {
67            if self.0.data.is_null() {
68                &mut []
69            } else {
70                unsafe { std::slice::from_raw_parts_mut(self.0.data, self.0.size) }
71            }
72        }
73
74        pub fn get_string(&self) -> String {
75            if let Ok(m) = String::from_utf8(self.as_slice().iter().map(|&c| c as u8).collect()) {
76                m
77            } else {
78                "".to_string()
79            }
80        }
81    }
82
83    impl<const N: usize> Drop for RosString<N> {
84        fn drop(&mut self) {
85            unsafe { rosidl_runtime_c__String__fini(&mut self.0 as *mut _) };
86        }
87    }
88
89    impl<const N: usize> Display for RosString<N> {
90        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91            let s = self.get_string();
92            write!(f, "{s}")
93        }
94    }
95
96    impl<const N: usize> PartialEq for RosString<N> {
97        fn eq(&self, other: &Self) -> bool {
98            unsafe { rosidl_runtime_c__String__are_equal(&self.0, &other.0) }
99        }
100    }
101
102    impl<const N: usize> TryClone for RosString<N> {
103        fn try_clone(&self) -> Option<Self> {
104            let mut result = Self::new(&self.get_string())?;
105            if unsafe { rosidl_runtime_c__String__copy(&self.0, &mut result.0) } {
106                Some(result)
107            } else {
108                None
109            }
110        }
111    }
112
113    impl<const N: usize> Clone for RosString<N> {
114        fn clone(&self) -> Self {
115            self.try_clone().unwrap()
116        }
117    }
118
119    impl<const N: usize> Default for RosString<N> {
120        fn default() -> Self {
121            Self::null()
122        }
123    }
124
125    unsafe impl<const N: usize> Sync for RosString<N> {}
126    unsafe impl<const N: usize> Send for RosString<N> {}
127
128    /// Sequence of string.
129    /// `STRLEN` represents the maximum number of characters excluding `\0`.
130    /// If `STRLEN` is `0`, the string is unlimited.
131    /// `SEQLEN` represents the maximum number of elements in a sequence.
132    /// If `SEQLEN` is `0`, the sequence is unlimited.
133    #[repr(C)]
134    #[derive(Debug)]
135    pub struct RosStringSeq<const STRLEN: usize, const SEQLEN: usize>(
136        rosidl_runtime_c__String__Sequence,
137    );
138
139    impl<const STRLEN: usize, const SEQLEN: usize> RosStringSeq<STRLEN, SEQLEN> {
140        pub fn new(size: usize) -> Option<Self> {
141            if SEQLEN != 0 && size > SEQLEN {
142                // the size exceeds the maximum number
143                return None;
144            }
145
146            let mut msg: rosidl_runtime_c__String__Sequence = unsafe { std::mem::zeroed() };
147            if unsafe { rosidl_runtime_c__String__Sequence__init(&mut msg, size as _) } {
148                Some(Self(msg))
149            } else {
150                None
151            }
152        }
153
154        pub fn null() -> Self {
155            let msg: rosidl_runtime_c__String__Sequence = unsafe { std::mem::zeroed() };
156            Self(msg)
157        }
158
159        pub fn as_slice(&self) -> &[RosString<STRLEN>] {
160            if self.0.data.is_null() {
161                &[]
162            } else {
163                let s = unsafe { std::slice::from_raw_parts(self.0.data, self.0.size) };
164                unsafe { transmute::<&[rosidl_runtime_c__String], &[RosString<STRLEN>]>(s) }
165            }
166        }
167
168        pub fn as_mut_slice(&mut self) -> &mut [RosString<STRLEN>] {
169            if self.0.data.is_null() {
170                &mut []
171            } else {
172                let s = unsafe {
173                    std::slice::from_raw_parts_mut(self.0.data, self.0.size.try_into().unwrap())
174                };
175                unsafe { transmute::<&mut [rosidl_runtime_c__String], &mut [RosString<STRLEN>]>(s) }
176            }
177        }
178
179        pub fn iter(&self) -> std::slice::Iter<'_, RosString<STRLEN>> {
180            self.as_slice().iter()
181        }
182
183        pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, RosString<STRLEN>> {
184            self.as_mut_slice().iter_mut()
185        }
186
187        pub fn len(&self) -> usize {
188            self.as_slice().len()
189        }
190
191        pub fn is_empty(&self) -> bool {
192            self.len() == 0
193        }
194    }
195
196    impl<const STRLEN: usize, const SEQLEN: usize> Drop for RosStringSeq<STRLEN, SEQLEN> {
197        fn drop(&mut self) {
198            unsafe { rosidl_runtime_c__String__Sequence__fini(&mut self.0 as *mut _) };
199        }
200    }
201
202    impl<const STRLEN: usize, const SEQLEN: usize> PartialEq for RosStringSeq<STRLEN, SEQLEN> {
203        fn eq(&self, other: &Self) -> bool {
204            unsafe {
205                rosidl_runtime_c__String__Sequence__are_equal(
206                    &self.0 as *const _,
207                    &other.0 as *const _,
208                )
209            }
210        }
211    }
212
213    impl<const STRLEN: usize, const SEQLEN: usize> TryClone for RosStringSeq<STRLEN, SEQLEN> {
214        fn try_clone(&self) -> Option<Self> {
215            let mut result = Self::new(self.0.size)?;
216            if unsafe { rosidl_runtime_c__String__Sequence__copy(&self.0, &mut result.0) } {
217                Some(result)
218            } else {
219                None
220            }
221        }
222    }
223
224    impl<const STRLEN: usize, const SEQLEN: usize> Clone for RosStringSeq<STRLEN, SEQLEN> {
225        fn clone(&self) -> Self {
226            self.try_clone().unwrap()
227        }
228    }
229
230    impl<const STRLEN: usize, const SEQLEN: usize> Default for RosStringSeq<STRLEN, SEQLEN> {
231        fn default() -> Self {
232            Self::null()
233        }
234    }
235
236    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Sync for RosStringSeq<STRLEN, SEQLEN> {}
237    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Send for RosStringSeq<STRLEN, SEQLEN> {}
238
239    /// WString.
240    /// `N` represents the maximum number of characters excluding `\0`.
241    /// If `N` is `0`, the string is unlimited.
242    #[repr(C)]
243    #[derive(Debug)]
244    pub struct RosWString<const N: usize>(rosidl_runtime_c__U16String);
245
246    impl<const N: usize> RosWString<N> {
247        pub fn new(s: &str) -> Option<Self> {
248            let mut msg: rosidl_runtime_c__U16String = unsafe { std::mem::zeroed() };
249
250            // initialize string
251            if unsafe { rosidl_runtime_c__U16String__init(&mut msg) } {
252                if Self::assign_string(&mut msg, s) {
253                    Some(Self(msg))
254                } else {
255                    None
256                }
257            } else {
258                None
259            }
260        }
261
262        pub fn null() -> Self {
263            let msg: rosidl_runtime_c__U16String = unsafe { std::mem::zeroed() };
264            Self(msg)
265        }
266
267        fn assign_string(msg: &mut rosidl_runtime_c__U16String, s: &str) -> bool {
268            let cs = widestring::U16CString::from_str(s).unwrap();
269
270            // assign string
271            if N == 0 {
272                unsafe { rosidl_runtime_c__U16String__assign(msg, cs.as_ptr()) }
273            } else {
274                unsafe { rosidl_runtime_c__U16String__assignn(msg, cs.as_ptr(), N as _) }
275            }
276        }
277
278        pub fn assign(&mut self, s: &str) -> bool {
279            Self::assign_string(&mut self.0, s)
280        }
281
282        pub fn as_slice(&self) -> &[u16] {
283            if self.0.data.is_null() {
284                &[]
285            } else {
286                unsafe { std::slice::from_raw_parts(self.0.data, self.0.size) }
287            }
288        }
289
290        pub fn as_mut_slice(&mut self) -> &mut [u16] {
291            if self.0.data.is_null() {
292                &mut []
293            } else {
294                unsafe { std::slice::from_raw_parts_mut(self.0.data, self.0.size) }
295            }
296        }
297
298        pub fn get_string(&self) -> String {
299            if let Ok(m) = String::from_utf16(self.as_slice()) {
300                m
301            } else {
302                "".to_string()
303            }
304        }
305    }
306
307    impl<const N: usize> Drop for RosWString<N> {
308        fn drop(&mut self) {
309            unsafe { rosidl_runtime_c__U16String__fini(&mut self.0 as *mut _) };
310        }
311    }
312
313    impl<const N: usize> Display for RosWString<N> {
314        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
315            let s = self.get_string();
316            write!(f, "{s}")
317        }
318    }
319
320    impl<const N: usize> PartialEq for RosWString<N> {
321        fn eq(&self, other: &Self) -> bool {
322            unsafe { rosidl_runtime_c__U16String__are_equal(&self.0, &other.0) }
323        }
324    }
325
326    impl<const N: usize> TryClone for RosWString<N> {
327        fn try_clone(&self) -> Option<Self> {
328            let mut result = Self::new(&self.get_string())?;
329            if unsafe { rosidl_runtime_c__U16String__copy(&self.0, &mut result.0) } {
330                Some(result)
331            } else {
332                None
333            }
334        }
335    }
336
337    impl<const N: usize> Clone for RosWString<N> {
338        fn clone(&self) -> Self {
339            self.try_clone().unwrap()
340        }
341    }
342
343    impl<const N: usize> Default for RosWString<N> {
344        fn default() -> Self {
345            Self::null()
346        }
347    }
348
349    unsafe impl<const N: usize> Sync for RosWString<N> {}
350    unsafe impl<const N: usize> Send for RosWString<N> {}
351
352    /// Sequence of WString.
353    /// `STRLEN` represents the maximum number of characters excluding `\0`.
354    /// If `STRLEN` is `0`, the string is unlimited.
355    /// `SEQLEN` represents the maximum number of elements in a sequence.
356    /// If `SEQLEN` is `0`, the sequence is unlimited.
357    #[repr(C)]
358    #[derive(Debug)]
359    pub struct RosWStringSeq<const STRLEN: usize, const SEQLEN: usize>(
360        rosidl_runtime_c__U16String__Sequence,
361    );
362
363    impl<const STRLEN: usize, const SEQLEN: usize> RosWStringSeq<STRLEN, SEQLEN> {
364        pub fn new(size: usize) -> Option<Self> {
365            if SEQLEN != 0 && size > SEQLEN {
366                // the size exceeds the maximum number
367                return None;
368            }
369
370            let mut msg: rosidl_runtime_c__U16String__Sequence = unsafe { std::mem::zeroed() };
371            if unsafe { rosidl_runtime_c__U16String__Sequence__init(&mut msg, size as _) } {
372                Some(Self(msg))
373            } else {
374                None
375            }
376        }
377
378        pub fn null() -> Self {
379            let msg: rosidl_runtime_c__U16String__Sequence = unsafe { std::mem::zeroed() };
380            Self(msg)
381        }
382
383        pub fn as_slice(&self) -> &[RosWString<STRLEN>] {
384            if self.0.data.is_null() {
385                &[]
386            } else {
387                let s = unsafe { std::slice::from_raw_parts(self.0.data, self.0.size) };
388                unsafe { transmute::<&[rosidl_runtime_c__U16String], &[RosWString<STRLEN>]>(s) }
389            }
390        }
391
392        pub fn as_mut_slice(&mut self) -> &mut [RosWString<STRLEN>] {
393            if self.0.data.is_null() {
394                &mut []
395            } else {
396                let s = unsafe {
397                    std::slice::from_raw_parts_mut(self.0.data, self.0.size.try_into().unwrap())
398                };
399                unsafe {
400                    transmute::<&mut [rosidl_runtime_c__U16String], &mut [RosWString<STRLEN>]>(s)
401                }
402            }
403        }
404
405        pub fn iter(&self) -> std::slice::Iter<'_, RosWString<STRLEN>> {
406            self.as_slice().iter()
407        }
408
409        pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, RosWString<STRLEN>> {
410            self.as_mut_slice().iter_mut()
411        }
412
413        pub fn len(&self) -> usize {
414            self.as_slice().len()
415        }
416
417        pub fn is_empty(&self) -> bool {
418            self.len() == 0
419        }
420    }
421
422    impl<const STRLEN: usize, const SEQLEN: usize> Drop for RosWStringSeq<STRLEN, SEQLEN> {
423        fn drop(&mut self) {
424            unsafe { rosidl_runtime_c__U16String__Sequence__fini(&mut self.0 as *mut _) };
425        }
426    }
427
428    impl<const STRLEN: usize, const SEQLEN: usize> PartialEq for RosWStringSeq<STRLEN, SEQLEN> {
429        fn eq(&self, other: &Self) -> bool {
430            unsafe {
431                rosidl_runtime_c__U16String__Sequence__are_equal(
432                    &self.0 as *const _,
433                    &other.0 as *const _,
434                )
435            }
436        }
437    }
438
439    impl<const STRLEN: usize, const SEQLEN: usize> TryClone for RosWStringSeq<STRLEN, SEQLEN> {
440        fn try_clone(&self) -> Option<Self> {
441            let mut result = Self::new(self.0.size)?;
442            if unsafe { rosidl_runtime_c__U16String__Sequence__copy(&self.0, &mut result.0) } {
443                Some(result)
444            } else {
445                None
446            }
447        }
448    }
449
450    impl<const STRLEN: usize, const SEQLEN: usize> Clone for RosWStringSeq<STRLEN, SEQLEN> {
451        fn clone(&self) -> Self {
452            self.try_clone().unwrap()
453        }
454    }
455
456    impl<const STRLEN: usize, const SEQLEN: usize> Default for RosWStringSeq<STRLEN, SEQLEN> {
457        fn default() -> Self {
458            Self::null()
459        }
460    }
461
462    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Sync for RosWStringSeq<STRLEN, SEQLEN> {}
463    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Send for RosWStringSeq<STRLEN, SEQLEN> {}
464}
465
466// ============================================================================
467// non-rcl feature - Pure Rust implementations
468// ============================================================================
469#[cfg(not(feature = "rcl"))]
470mod non_rcl_impl {
471    use super::*;
472    use ros2_types::serde::{Deserialize, Deserializer, Serialize, Serializer};
473
474    /// String.
475    /// `N` represents the maximum number of characters excluding `\0`.
476    /// If `N` is `0`, the string is unlimited.
477    #[derive(Debug)]
478    pub struct RosString<const N: usize>(String);
479
480    impl<const N: usize> RosString<N> {
481        pub fn new(s: &str) -> Option<Self> {
482            // Check length constraint if N > 0
483            if N > 0 && s.len() > N {
484                return None;
485            }
486            Some(Self(s.to_string()))
487        }
488
489        pub fn null() -> Self {
490            Self(String::new())
491        }
492
493        pub fn assign(&mut self, s: &str) -> bool {
494            // Check length constraint if N > 0
495            if N > 0 && s.len() > N {
496                return false;
497            }
498            self.0 = s.to_string();
499            true
500        }
501
502        pub fn get_string(&self) -> String {
503            self.0.clone()
504        }
505
506        pub fn as_bytes(&self) -> &[u8] {
507            self.0.as_bytes()
508        }
509    }
510
511    impl<const N: usize> Display for RosString<N> {
512        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
513            write!(f, "{}", self.0)
514        }
515    }
516
517    impl<const N: usize> PartialEq for RosString<N> {
518        fn eq(&self, other: &Self) -> bool {
519            self.0 == other.0
520        }
521    }
522
523    impl<const N: usize> TryClone for RosString<N> {
524        fn try_clone(&self) -> Option<Self> {
525            Some(Self(self.0.clone()))
526        }
527    }
528
529    impl<const N: usize> Clone for RosString<N> {
530        fn clone(&self) -> Self {
531            Self(self.0.clone())
532        }
533    }
534
535    impl<const N: usize> Default for RosString<N> {
536        fn default() -> Self {
537            Self::null()
538        }
539    }
540
541    impl<const N: usize> Serialize for RosString<N> {
542        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
543        where
544            S: Serializer,
545        {
546            self.0.serialize(serializer)
547        }
548    }
549
550    impl<'de, const N: usize> Deserialize<'de> for RosString<N> {
551        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
552        where
553            D: Deserializer<'de>,
554        {
555            let s = String::deserialize(deserializer)?;
556            if N > 0 && s.len() > N {
557                return Err(ros2_types::serde::de::Error::custom(format!(
558                    "string length {} exceeds maximum {}",
559                    s.len(),
560                    N
561                )));
562            }
563            Ok(Self(s))
564        }
565    }
566
567    unsafe impl<const N: usize> Sync for RosString<N> {}
568    unsafe impl<const N: usize> Send for RosString<N> {}
569
570    /// Sequence of string.
571    /// `STRLEN` represents the maximum number of characters excluding `\0`.
572    /// If `STRLEN` is `0`, the string is unlimited.
573    /// `SEQLEN` represents the maximum number of elements in a sequence.
574    /// If `SEQLEN` is `0`, the sequence is unlimited.
575    #[derive(Debug)]
576    pub struct RosStringSeq<const STRLEN: usize, const SEQLEN: usize>(Vec<RosString<STRLEN>>);
577
578    impl<const STRLEN: usize, const SEQLEN: usize> RosStringSeq<STRLEN, SEQLEN> {
579        pub fn new(size: usize) -> Option<Self> {
580            if SEQLEN != 0 && size > SEQLEN {
581                // the size exceeds the maximum number
582                return None;
583            }
584            let mut v = Vec::with_capacity(size);
585            for _ in 0..size {
586                v.push(RosString::null());
587            }
588            Some(Self(v))
589        }
590
591        pub fn null() -> Self {
592            Self(Vec::new())
593        }
594
595        pub fn as_slice(&self) -> &[RosString<STRLEN>] {
596            &self.0
597        }
598
599        pub fn as_mut_slice(&mut self) -> &mut [RosString<STRLEN>] {
600            &mut self.0
601        }
602
603        pub fn iter(&self) -> std::slice::Iter<'_, RosString<STRLEN>> {
604            self.0.iter()
605        }
606
607        pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, RosString<STRLEN>> {
608            self.0.iter_mut()
609        }
610
611        pub fn len(&self) -> usize {
612            self.0.len()
613        }
614
615        pub fn is_empty(&self) -> bool {
616            self.0.is_empty()
617        }
618    }
619
620    impl<const STRLEN: usize, const SEQLEN: usize> PartialEq for RosStringSeq<STRLEN, SEQLEN> {
621        fn eq(&self, other: &Self) -> bool {
622            self.0 == other.0
623        }
624    }
625
626    impl<const STRLEN: usize, const SEQLEN: usize> TryClone for RosStringSeq<STRLEN, SEQLEN> {
627        fn try_clone(&self) -> Option<Self> {
628            Some(Self(self.0.clone()))
629        }
630    }
631
632    impl<const STRLEN: usize, const SEQLEN: usize> Clone for RosStringSeq<STRLEN, SEQLEN> {
633        fn clone(&self) -> Self {
634            Self(self.0.clone())
635        }
636    }
637
638    impl<const STRLEN: usize, const SEQLEN: usize> Default for RosStringSeq<STRLEN, SEQLEN> {
639        fn default() -> Self {
640            Self::null()
641        }
642    }
643
644    impl<const STRLEN: usize, const SEQLEN: usize> Serialize for RosStringSeq<STRLEN, SEQLEN> {
645        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
646        where
647            S: Serializer,
648        {
649            self.0.serialize(serializer)
650        }
651    }
652
653    impl<'de, const STRLEN: usize, const SEQLEN: usize> Deserialize<'de>
654        for RosStringSeq<STRLEN, SEQLEN>
655    {
656        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
657        where
658            D: Deserializer<'de>,
659        {
660            let vec = Vec::<RosString<STRLEN>>::deserialize(deserializer)?;
661            if SEQLEN != 0 && vec.len() > SEQLEN {
662                return Err(ros2_types::serde::de::Error::custom(format!(
663                    "sequence length {} exceeds maximum {}",
664                    vec.len(),
665                    SEQLEN
666                )));
667            }
668            Ok(Self(vec))
669        }
670    }
671
672    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Sync for RosStringSeq<STRLEN, SEQLEN> {}
673    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Send for RosStringSeq<STRLEN, SEQLEN> {}
674
675    /// WString.
676    /// `N` represents the maximum number of characters excluding `\0`.
677    /// If `N` is `0`, the string is unlimited.
678    #[derive(Debug)]
679    pub struct RosWString<const N: usize>(String);
680
681    impl<const N: usize> RosWString<N> {
682        pub fn new(s: &str) -> Option<Self> {
683            // Check length constraint if N > 0 (count UTF-16 code units)
684            if N > 0 && s.encode_utf16().count() > N {
685                return None;
686            }
687            Some(Self(s.to_string()))
688        }
689
690        pub fn null() -> Self {
691            Self(String::new())
692        }
693
694        pub fn assign(&mut self, s: &str) -> bool {
695            // Check length constraint if N > 0 (count UTF-16 code units)
696            if N > 0 && s.encode_utf16().count() > N {
697                return false;
698            }
699            self.0 = s.to_string();
700            true
701        }
702
703        pub fn get_string(&self) -> String {
704            self.0.clone()
705        }
706
707        pub fn as_utf16(&self) -> Vec<u16> {
708            self.0.encode_utf16().collect()
709        }
710    }
711
712    impl<const N: usize> Display for RosWString<N> {
713        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714            write!(f, "{}", self.0)
715        }
716    }
717
718    impl<const N: usize> PartialEq for RosWString<N> {
719        fn eq(&self, other: &Self) -> bool {
720            self.0 == other.0
721        }
722    }
723
724    impl<const N: usize> TryClone for RosWString<N> {
725        fn try_clone(&self) -> Option<Self> {
726            Some(Self(self.0.clone()))
727        }
728    }
729
730    impl<const N: usize> Clone for RosWString<N> {
731        fn clone(&self) -> Self {
732            Self(self.0.clone())
733        }
734    }
735
736    impl<const N: usize> Default for RosWString<N> {
737        fn default() -> Self {
738            Self::null()
739        }
740    }
741
742    impl<const N: usize> Serialize for RosWString<N> {
743        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
744        where
745            S: Serializer,
746        {
747            self.0.serialize(serializer)
748        }
749    }
750
751    impl<'de, const N: usize> Deserialize<'de> for RosWString<N> {
752        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
753        where
754            D: Deserializer<'de>,
755        {
756            let s = String::deserialize(deserializer)?;
757            if N > 0 && s.encode_utf16().count() > N {
758                return Err(ros2_types::serde::de::Error::custom(format!(
759                    "wstring length exceeds maximum {}",
760                    N
761                )));
762            }
763            Ok(Self(s))
764        }
765    }
766
767    unsafe impl<const N: usize> Sync for RosWString<N> {}
768    unsafe impl<const N: usize> Send for RosWString<N> {}
769
770    /// Sequence of WString.
771    /// `STRLEN` represents the maximum number of characters excluding `\0`.
772    /// If `STRLEN` is `0`, the string is unlimited.
773    /// `SEQLEN` represents the maximum number of elements in a sequence.
774    /// If `SEQLEN` is `0`, the sequence is unlimited.
775    #[derive(Debug)]
776    pub struct RosWStringSeq<const STRLEN: usize, const SEQLEN: usize>(Vec<RosWString<STRLEN>>);
777
778    impl<const STRLEN: usize, const SEQLEN: usize> RosWStringSeq<STRLEN, SEQLEN> {
779        pub fn new(size: usize) -> Option<Self> {
780            if SEQLEN != 0 && size > SEQLEN {
781                // the size exceeds the maximum number
782                return None;
783            }
784            let mut v = Vec::with_capacity(size);
785            for _ in 0..size {
786                v.push(RosWString::null());
787            }
788            Some(Self(v))
789        }
790
791        pub fn null() -> Self {
792            Self(Vec::new())
793        }
794
795        pub fn as_slice(&self) -> &[RosWString<STRLEN>] {
796            &self.0
797        }
798
799        pub fn as_mut_slice(&mut self) -> &mut [RosWString<STRLEN>] {
800            &mut self.0
801        }
802
803        pub fn iter(&self) -> std::slice::Iter<'_, RosWString<STRLEN>> {
804            self.0.iter()
805        }
806
807        pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, RosWString<STRLEN>> {
808            self.0.iter_mut()
809        }
810
811        pub fn len(&self) -> usize {
812            self.0.len()
813        }
814
815        pub fn is_empty(&self) -> bool {
816            self.0.is_empty()
817        }
818    }
819
820    impl<const STRLEN: usize, const SEQLEN: usize> PartialEq for RosWStringSeq<STRLEN, SEQLEN> {
821        fn eq(&self, other: &Self) -> bool {
822            self.0 == other.0
823        }
824    }
825
826    impl<const STRLEN: usize, const SEQLEN: usize> TryClone for RosWStringSeq<STRLEN, SEQLEN> {
827        fn try_clone(&self) -> Option<Self> {
828            Some(Self(self.0.clone()))
829        }
830    }
831
832    impl<const STRLEN: usize, const SEQLEN: usize> Clone for RosWStringSeq<STRLEN, SEQLEN> {
833        fn clone(&self) -> Self {
834            Self(self.0.clone())
835        }
836    }
837
838    impl<const STRLEN: usize, const SEQLEN: usize> Default for RosWStringSeq<STRLEN, SEQLEN> {
839        fn default() -> Self {
840            Self::null()
841        }
842    }
843
844    impl<const STRLEN: usize, const SEQLEN: usize> Serialize for RosWStringSeq<STRLEN, SEQLEN> {
845        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
846        where
847            S: Serializer,
848        {
849            self.0.serialize(serializer)
850        }
851    }
852
853    impl<'de, const STRLEN: usize, const SEQLEN: usize> Deserialize<'de>
854        for RosWStringSeq<STRLEN, SEQLEN>
855    {
856        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
857        where
858            D: Deserializer<'de>,
859        {
860            let vec = Vec::<RosWString<STRLEN>>::deserialize(deserializer)?;
861            if SEQLEN != 0 && vec.len() > SEQLEN {
862                return Err(ros2_types::serde::de::Error::custom(format!(
863                    "sequence length {} exceeds maximum {}",
864                    vec.len(),
865                    SEQLEN
866                )));
867            }
868            Ok(Self(vec))
869        }
870    }
871
872    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Sync for RosWStringSeq<STRLEN, SEQLEN> {}
873    unsafe impl<const STRLEN: usize, const SEQLEN: usize> Send for RosWStringSeq<STRLEN, SEQLEN> {}
874}
875
876// ============================================================================
877// Re-exports
878// ============================================================================
879#[cfg(feature = "rcl")]
880pub use rcl_impl::*;
881
882#[cfg(not(feature = "rcl"))]
883pub use non_rcl_impl::*;
884
885// ============================================================================
886// RosFieldType implementations for string types
887// ============================================================================
888
889use ros2_types::RosFieldType;
890use ros2_types::types::FieldType;
891
892impl<const N: usize> RosFieldType for RosString<N> {
893    fn ros_field_type() -> FieldType {
894        if N == 0 {
895            FieldType::primitive(ros2_types::FIELD_TYPE_STRING)
896        } else {
897            FieldType::bounded_string(N as u64)
898        }
899    }
900}
901
902impl<const N: usize> RosFieldType for RosWString<N> {
903    fn ros_field_type() -> FieldType {
904        if N == 0 {
905            FieldType::primitive(ros2_types::FIELD_TYPE_WSTRING)
906        } else {
907            FieldType::bounded_wstring(N as u64)
908        }
909    }
910}
911
912impl<const STRLEN: usize, const SEQLEN: usize> RosFieldType for RosStringSeq<STRLEN, SEQLEN> {
913    fn ros_field_type() -> FieldType {
914        // STRLEN=0 means unbounded string, STRLEN>0 means bounded string
915        // SEQLEN=0 means unbounded sequence, SEQLEN>0 means bounded sequence
916        let type_id = if STRLEN == 0 {
917            ros2_types::FIELD_TYPE_STRING
918        } else {
919            ros2_types::FIELD_TYPE_BOUNDED_STRING
920        };
921
922        if SEQLEN == 0 {
923            FieldType::sequence_with_string_capacity(type_id, STRLEN as u64)
924        } else {
925            FieldType::bounded_sequence_with_string_capacity(type_id, SEQLEN as u64, STRLEN as u64)
926        }
927    }
928}
929
930impl<const STRLEN: usize, const SEQLEN: usize> RosFieldType for RosWStringSeq<STRLEN, SEQLEN> {
931    fn ros_field_type() -> FieldType {
932        let type_id = if STRLEN == 0 {
933            ros2_types::FIELD_TYPE_WSTRING
934        } else {
935            ros2_types::FIELD_TYPE_BOUNDED_WSTRING
936        };
937
938        if SEQLEN == 0 {
939            FieldType::sequence_with_string_capacity(type_id, STRLEN as u64)
940        } else {
941            FieldType::bounded_sequence_with_string_capacity(type_id, SEQLEN as u64, STRLEN as u64)
942        }
943    }
944}