ros_message/
value.rs

1use crate::{Duration, Time};
2use itertools::Itertools;
3use serde_derive::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::convert::{TryFrom, TryInto};
6use std::fmt;
7use std::fmt::{Display, Formatter};
8use std::iter::FromIterator;
9
10/// Represents an arbitrary ROS message.
11pub type MessageValue = HashMap<String, Value>;
12
13/// Represents an arbitrary ROS message or value in it.
14#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15pub enum Value {
16    /// Represents `bool`.
17    Bool(bool),
18    /// Represents `int8` or `byte`.
19    I8(i8),
20    /// Represents `int16`.
21    I16(i16),
22    /// Represents `int32`.
23    I32(i32),
24    /// Represents `int64`.
25    I64(i64),
26    /// Represents `uint8` or `char`.
27    U8(u8),
28    /// Represents `uint16`.
29    U16(u16),
30    /// Represents `uint32`.
31    U32(u32),
32    /// Represents `uint64`.
33    U64(u64),
34    /// Represents `float32`.
35    F32(f32),
36    /// Represents `float64`.
37    F64(f64),
38    /// Represents `string`.
39    String(String),
40    /// Represents `time`.
41    Time(Time),
42    /// Represents `duration`.
43    Duration(Duration),
44    /// Represents `some_type[]` or `some_type[length]`.
45    ///
46    /// For example: `float32[64]`, `geometry_msgs/Point[]`.
47    Array(Vec<Value>),
48    /// Represents an embedded message.
49    Message(MessageValue),
50}
51
52impl Value {
53    fn fmt_indented(&self, indentation: usize, step: usize, f: &mut Formatter<'_>) -> fmt::Result {
54        match self {
55            Value::Bool(v) => v.fmt(f),
56            Value::I8(v) => v.fmt(f),
57            Value::I16(v) => v.fmt(f),
58            Value::I32(v) => v.fmt(f),
59            Value::I64(v) => v.fmt(f),
60            Value::U8(v) => v.fmt(f),
61            Value::U16(v) => v.fmt(f),
62            Value::U32(v) => v.fmt(f),
63            Value::U64(v) => v.fmt(f),
64            Value::F32(v) => v.fmt(f),
65            Value::F64(v) => v.fmt(f),
66            Value::String(v) => write!(f, "{:?}", v),
67            Value::Time(v) => v.fmt(f),
68            Value::Duration(v) => v.fmt(f),
69            Value::Array(items) => {
70                for item in items {
71                    writeln!(f)?;
72                    write!(f, "{:indent$}- ", "", indent = indentation)?;
73                    item.fmt_indented(indentation + step, step, f)?;
74                }
75                Ok(())
76            }
77            Value::Message(items) => {
78                for (key, item) in items.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0)) {
79                    writeln!(f)?;
80                    write!(f, "{:indent$}{}: ", "", key, indent = indentation)?;
81                    item.fmt_indented(indentation + step, step, f)?;
82                }
83                Ok(())
84            }
85        }
86    }
87
88    /// Returns the content if `Value` is a `bool`.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// # use ros_message::Value;
94    /// assert_eq!(Value::Bool(true).as_bool(), Some(true));
95    /// assert_eq!(Value::Bool(false).as_bool(), Some(false));
96    /// assert!(Value::U32(12).as_bool().is_none());
97    /// ```
98    pub fn as_bool(&self) -> Option<bool> {
99        if let Value::Bool(value) = self {
100            Some(*value)
101        } else {
102            None
103        }
104    }
105
106    /// Returns the content if `Value` is an `i8`.
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// # use ros_message::Value;
112    /// assert_eq!(Value::I8(12).as_i8(), Some(12));
113    /// assert!(Value::U32(12).as_i8().is_none());
114    /// ```
115    pub fn as_i8(&self) -> Option<i8> {
116        if let Value::I8(value) = self {
117            Some(*value)
118        } else {
119            None
120        }
121    }
122
123    /// Returns the content if `Value` is an `i16`.
124    ///
125    /// # Examples
126    ///
127    /// ```
128    /// # use ros_message::Value;
129    /// assert_eq!(Value::I16(12).as_i16(), Some(12));
130    /// assert!(Value::U32(12).as_i16().is_none());
131    /// ```
132    pub fn as_i16(&self) -> Option<i16> {
133        if let Value::I16(value) = self {
134            Some(*value)
135        } else {
136            None
137        }
138    }
139
140    /// Returns the content if `Value` is an `i32`.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// # use ros_message::Value;
146    /// assert_eq!(Value::I32(12).as_i32(), Some(12));
147    /// assert!(Value::U32(12).as_i32().is_none());
148    /// ```
149    pub fn as_i32(&self) -> Option<i32> {
150        if let Value::I32(value) = self {
151            Some(*value)
152        } else {
153            None
154        }
155    }
156
157    /// Returns the content if `Value` is an `i64`.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// # use ros_message::Value;
163    /// assert_eq!(Value::I64(12).as_i64(), Some(12));
164    /// assert!(Value::U32(12).as_i64().is_none());
165    /// ```
166    pub fn as_i64(&self) -> Option<i64> {
167        if let Value::I64(value) = self {
168            Some(*value)
169        } else {
170            None
171        }
172    }
173
174    /// Returns the content if `Value` is a `u8`.
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// # use ros_message::Value;
180    /// assert_eq!(Value::U8(12).as_u8(), Some(12));
181    /// assert!(Value::U32(12).as_u8().is_none());
182    /// ```
183    pub fn as_u8(&self) -> Option<u8> {
184        if let Value::U8(value) = self {
185            Some(*value)
186        } else {
187            None
188        }
189    }
190
191    /// Returns the content if `Value` is a `u16`.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// # use ros_message::Value;
197    /// assert_eq!(Value::U16(12).as_u16(), Some(12));
198    /// assert!(Value::U32(12).as_u16().is_none());
199    /// ```
200    pub fn as_u16(&self) -> Option<u16> {
201        if let Value::U16(value) = self {
202            Some(*value)
203        } else {
204            None
205        }
206    }
207
208    /// Returns the content if `Value` is a `u32`.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// # use ros_message::Value;
214    /// assert_eq!(Value::U32(12).as_u32(), Some(12));
215    /// assert!(Value::U16(12).as_u32().is_none());
216    /// ```
217    pub fn as_u32(&self) -> Option<u32> {
218        if let Value::U32(value) = self {
219            Some(*value)
220        } else {
221            None
222        }
223    }
224
225    /// Returns the content if `Value` is a `u64`.
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// # use ros_message::Value;
231    /// assert_eq!(Value::U64(12).as_u64(), Some(12));
232    /// assert!(Value::U32(12).as_u64().is_none());
233    /// ```
234    pub fn as_u64(&self) -> Option<u64> {
235        if let Value::U64(value) = self {
236            Some(*value)
237        } else {
238            None
239        }
240    }
241
242    /// Returns the content if `Value` is an `f32`.
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// # use ros_message::Value;
248    /// assert_eq!(Value::F32(12.0).as_f32(), Some(12.0));
249    /// assert!(Value::U32(12).as_f32().is_none());
250    /// ```
251    pub fn as_f32(&self) -> Option<f32> {
252        if let Value::F32(value) = self {
253            Some(*value)
254        } else {
255            None
256        }
257    }
258
259    /// Returns the content if `Value` is an `f64`.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// # use ros_message::Value;
265    /// assert_eq!(Value::F64(12.0).as_f64(), Some(12.0));
266    /// assert!(Value::U32(12).as_f64().is_none());
267    /// ```
268    pub fn as_f64(&self) -> Option<f64> {
269        if let Value::F64(value) = self {
270            Some(*value)
271        } else {
272            None
273        }
274    }
275
276    /// Returns a `&str` if `Value` is a `String`.
277    ///
278    /// # Examples
279    ///
280    /// ```
281    /// # use ros_message::Value;
282    /// assert_eq!(Value::String("foo".into()).as_str(), Some("foo"));
283    /// assert!(Value::U32(12).as_str().is_none());
284    /// ```
285    pub fn as_str(&self) -> Option<&str> {
286        if let Value::String(value) = self {
287            Some(value)
288        } else {
289            None
290        }
291    }
292
293    /// Returns the content if `Value` is a `String`.
294    ///
295    /// # Examples
296    ///
297    /// ```
298    /// # use ros_message::Value;
299    /// assert_eq!(Value::String("foo".into()).try_into_string(), Some("foo".into()));
300    /// assert!(Value::U32(12).try_into_string().is_none());
301    /// ```
302    pub fn try_into_string(self) -> Option<String> {
303        if let Value::String(value) = self {
304            Some(value)
305        } else {
306            None
307        }
308    }
309
310    /// Returns the content if `Value` is a `Time` struct.
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// # use ros_message::{Time, Value};
316    /// assert_eq!(
317    ///     Value::Time(Time::from_nanos(120)).as_time(),
318    ///     Some(Time::from_nanos(120)),
319    /// );
320    /// assert!(Value::U32(12).as_time().is_none());
321    /// ```
322    pub fn as_time(&self) -> Option<Time> {
323        if let Value::Time(value) = self {
324            Some(*value)
325        } else {
326            None
327        }
328    }
329
330    /// Returns the content if `Value` is a `Duration` struct.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// # use ros_message::{Duration, Value};
336    /// assert_eq!(
337    ///     Value::Duration(Duration::from_nanos(120)).as_duration(),
338    ///     Some(Duration::from_nanos(120)),
339    /// );
340    /// assert!(Value::U32(12).as_duration().is_none());
341    /// ```
342    pub fn as_duration(&self) -> Option<Duration> {
343        if let Value::Duration(value) = self {
344            Some(*value)
345        } else {
346            None
347        }
348    }
349
350    /// Returns a reference to the content if `Value` is an array.
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// # use ros_message::Value;
356    /// assert_eq!(
357    ///     Value::Array(vec![1u32.into(), 2u32.into(), 3u32.into()]).as_slice(),
358    ///     Some(&[Value::U32(1), Value::U32(2), Value::U32(3)][..]),
359    /// );
360    /// assert!(Value::U32(12).as_slice().is_none());
361    /// ```
362    pub fn as_slice(&self) -> Option<&[Value]> {
363        if let Value::Array(value) = self {
364            Some(value)
365        } else {
366            None
367        }
368    }
369
370    /// Returns the content if `Value` is an array.
371    ///
372    /// # Examples
373    ///
374    /// ```
375    /// # use ros_message::Value;
376    /// assert_eq!(
377    ///     Value::Array(vec![1u32.into(), 2u32.into(), 3u32.into()]).try_into_vec(),
378    ///     Some(vec![Value::U32(1), Value::U32(2), Value::U32(3)]),
379    /// );
380    /// assert!(Value::U32(12).try_into_vec().is_none());
381    /// ```
382    pub fn try_into_vec(self) -> Option<Vec<Value>> {
383        if let Value::Array(value) = self {
384            Some(value)
385        } else {
386            None
387        }
388    }
389
390    /// Returns a reference to the content if `Value` is a message.
391    ///
392    /// # Examples
393    ///
394    /// ```
395    /// # use ros_message::Value;
396    /// # use std::collections::HashMap;
397    /// let mut data = HashMap::<String, Value>::new();
398    /// data.insert("foo".into(), true.into());
399    /// data.insert("bar".into(), false.into());
400    /// assert_eq!(Value::Message(data.clone()).as_map(), Some(&data));
401    /// assert!(Value::U32(12).as_map().is_none());
402    /// ```
403    pub fn as_map(&self) -> Option<&MessageValue> {
404        if let Value::Message(value) = self {
405            Some(value)
406        } else {
407            None
408        }
409    }
410
411    /// Returns the content if `Value` is a message.
412    ///
413    /// # Examples
414    ///
415    /// ```
416    /// # use ros_message::Value;
417    /// # use std::collections::HashMap;
418    /// let mut data = HashMap::<String, Value>::new();
419    /// data.insert("foo".into(), true.into());
420    /// data.insert("bar".into(), false.into());
421    /// assert_eq!(Value::Message(data.clone()).try_into_map(), Some(data));
422    /// assert!(Value::U32(12).try_into_map().is_none());
423    /// ```
424    pub fn try_into_map(self) -> Option<MessageValue> {
425        if let Value::Message(value) = self {
426            Some(value)
427        } else {
428            None
429        }
430    }
431}
432
433impl Display for Value {
434    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
435        self.fmt_indented(0, 2, f)
436    }
437}
438
439impl From<bool> for Value {
440    fn from(v: bool) -> Self {
441        Self::Bool(v)
442    }
443}
444
445impl From<i8> for Value {
446    fn from(v: i8) -> Self {
447        Self::I8(v)
448    }
449}
450
451impl From<i16> for Value {
452    fn from(v: i16) -> Self {
453        Self::I16(v)
454    }
455}
456
457impl From<i32> for Value {
458    fn from(v: i32) -> Self {
459        Self::I32(v)
460    }
461}
462
463impl From<i64> for Value {
464    fn from(v: i64) -> Self {
465        Self::I64(v)
466    }
467}
468
469impl From<u8> for Value {
470    fn from(v: u8) -> Self {
471        Self::U8(v)
472    }
473}
474
475impl From<u16> for Value {
476    fn from(v: u16) -> Self {
477        Self::U16(v)
478    }
479}
480
481impl From<u32> for Value {
482    fn from(v: u32) -> Self {
483        Self::U32(v)
484    }
485}
486
487impl From<u64> for Value {
488    fn from(v: u64) -> Self {
489        Self::U64(v)
490    }
491}
492
493impl From<f32> for Value {
494    fn from(v: f32) -> Self {
495        Self::F32(v)
496    }
497}
498
499impl From<f64> for Value {
500    fn from(v: f64) -> Self {
501        Self::F64(v)
502    }
503}
504
505impl From<String> for Value {
506    fn from(v: String) -> Self {
507        Self::String(v)
508    }
509}
510
511impl From<Time> for Value {
512    fn from(v: Time) -> Self {
513        Self::Time(v)
514    }
515}
516
517impl From<Duration> for Value {
518    fn from(v: Duration) -> Self {
519        Self::Duration(v)
520    }
521}
522
523impl<T: Into<Value>> From<Vec<T>> for Value {
524    fn from(v: Vec<T>) -> Self {
525        Self::Array(v.into_iter().map(Into::into).collect())
526    }
527}
528
529impl<T: Into<Value>, const L: usize> From<[T; L]> for Value {
530    fn from(v: [T; L]) -> Self {
531        Self::Array(IntoIterator::into_iter(v).map(Into::into).collect())
532    }
533}
534
535impl From<HashMap<String, Value>> for Value {
536    fn from(v: HashMap<String, Value>) -> Self {
537        Self::Message(v)
538    }
539}
540
541impl TryFrom<Value> for bool {
542    type Error = ();
543
544    fn try_from(value: Value) -> Result<Self, Self::Error> {
545        value.as_bool().ok_or(())
546    }
547}
548
549impl TryFrom<Value> for i8 {
550    type Error = ();
551
552    fn try_from(value: Value) -> Result<Self, Self::Error> {
553        value.as_i8().ok_or(())
554    }
555}
556
557impl TryFrom<Value> for i16 {
558    type Error = ();
559
560    fn try_from(value: Value) -> Result<Self, Self::Error> {
561        value.as_i16().ok_or(())
562    }
563}
564
565impl TryFrom<Value> for i32 {
566    type Error = ();
567
568    fn try_from(value: Value) -> Result<Self, Self::Error> {
569        value.as_i32().ok_or(())
570    }
571}
572
573impl TryFrom<Value> for i64 {
574    type Error = ();
575
576    fn try_from(value: Value) -> Result<Self, Self::Error> {
577        value.as_i64().ok_or(())
578    }
579}
580
581impl TryFrom<Value> for u8 {
582    type Error = ();
583
584    fn try_from(value: Value) -> Result<Self, Self::Error> {
585        value.as_u8().ok_or(())
586    }
587}
588
589impl TryFrom<Value> for u16 {
590    type Error = ();
591
592    fn try_from(value: Value) -> Result<Self, Self::Error> {
593        value.as_u16().ok_or(())
594    }
595}
596
597impl TryFrom<Value> for u32 {
598    type Error = ();
599
600    fn try_from(value: Value) -> Result<Self, Self::Error> {
601        value.as_u32().ok_or(())
602    }
603}
604
605impl TryFrom<Value> for u64 {
606    type Error = ();
607
608    fn try_from(value: Value) -> Result<Self, Self::Error> {
609        value.as_u64().ok_or(())
610    }
611}
612
613impl TryFrom<Value> for f32 {
614    type Error = ();
615
616    fn try_from(value: Value) -> Result<Self, Self::Error> {
617        value.as_f32().ok_or(())
618    }
619}
620
621impl TryFrom<Value> for f64 {
622    type Error = ();
623
624    fn try_from(value: Value) -> Result<Self, Self::Error> {
625        value.as_f64().ok_or(())
626    }
627}
628
629impl TryFrom<Value> for String {
630    type Error = ();
631
632    fn try_from(value: Value) -> Result<Self, Self::Error> {
633        value.try_into_string().ok_or(())
634    }
635}
636
637impl TryFrom<Value> for Time {
638    type Error = ();
639
640    fn try_from(value: Value) -> Result<Self, Self::Error> {
641        value.as_time().ok_or(())
642    }
643}
644
645impl TryFrom<Value> for Duration {
646    type Error = ();
647
648    fn try_from(value: Value) -> Result<Self, Self::Error> {
649        value.as_duration().ok_or(())
650    }
651}
652
653impl<T: TryFrom<Value>> TryFrom<Value> for Vec<T> {
654    type Error = ();
655
656    fn try_from(value: Value) -> Result<Self, Self::Error> {
657        let value = value.try_into_vec().ok_or(())?;
658        value
659            .into_iter()
660            .map(TryInto::try_into)
661            .collect::<Result<Self, _>>()
662            .map_err(|_| ())
663    }
664}
665
666impl<T: TryFrom<Value>, const L: usize> TryFrom<Value> for [T; L] {
667    type Error = ();
668
669    fn try_from(value: Value) -> Result<Self, Self::Error> {
670        let value = value.try_into_vec().ok_or(())?;
671        if value.len() != L {
672            return Err(());
673        }
674        array_init::from_iter(value.into_iter().filter_map(|v| v.try_into().ok())).ok_or(())
675    }
676}
677
678impl TryFrom<Value> for HashMap<String, Value> {
679    type Error = ();
680
681    fn try_from(value: Value) -> Result<Self, Self::Error> {
682        value.try_into_map().ok_or(())
683    }
684}
685
686impl<K: Into<String>, T: Into<Value>> FromIterator<(K, T)> for Value {
687    fn from_iter<I: IntoIterator<Item = (K, T)>>(iter: I) -> Self {
688        Self::Message(
689            iter.into_iter()
690                .map(|(key, value)| (key.into(), value.into()))
691                .collect(),
692        )
693    }
694}
695
696impl<T: Into<Value>> FromIterator<T> for Value {
697    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
698        Self::Array(iter.into_iter().map(Into::into).collect())
699    }
700}