serde_xmlrpc/value/
mod.rs

1use std::{collections::BTreeMap, convert::TryFrom};
2
3use iso8601::DateTime;
4
5pub mod de;
6pub mod ser;
7
8pub use de::Deserializer;
9pub use ser::Serializer;
10
11/// Convert a `T` into `serde_xmlrpc::Value` which is an enum that can represent
12/// any valid XML-RPC data.
13///
14/// # Example
15///
16/// ```
17/// #[derive(serde::Serialize)]
18/// struct Custom {
19///     field: i32,
20/// }
21///
22/// let param = Custom {
23///     field: 42
24/// };
25///
26/// let _value = serde_xmlrpc::to_value(param).unwrap();
27/// ```
28pub fn to_value<T>(value: T) -> crate::Result<Value>
29where
30    T: serde::Serialize,
31{
32    value.serialize(Serializer)
33}
34
35/// Represents any single valid xmlrpc "Value"
36#[derive(Clone, Debug, PartialEq)]
37pub enum Value {
38    /// A 32-bit signed integer (`<i4>` or `<int>`).
39    Int(i32),
40    /// A 64-bit signed integer (`<i8>`).
41    Int64(i64),
42    /// A boolean value (`<boolean>`, 0 == `false`, 1 == `true`).
43    Bool(bool),
44    /// A string (`<string>`).
45    String(String),
46    /// A double-precision IEEE 754 floating point number (`<double>`).
47    Double(f64),
48    /// An ISO 8601 formatted date/time value (`<dateTime.iso8601>`).
49    DateTime(DateTime),
50    /// Base64-encoded binary data (`<base64>`).
51    Base64(Vec<u8>),
52    /// A mapping of named values (`<struct>`).
53    Struct(BTreeMap<String, Value>),
54    /// A list of arbitrary (heterogeneous) values (`<array>`).
55    Array(Vec<Value>),
56    /// The empty (Unit) value (`<nil/>`).
57    Nil,
58}
59
60// Public API definitions
61impl Value {
62    /// Returns an inner struct or array value indexed by `index`.
63    ///
64    /// Returns `None` if the member doesn't exist or `self` is neither a struct nor an array.
65    ///
66    /// You can also use Rust's square-bracket indexing syntax to perform this operation if you want
67    /// a default value instead of an `Option`. Refer to the top-level [examples](#examples) for
68    /// details.
69    /*
70    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
71        index.get(self)
72    }
73    */
74
75    /// If the `Value` is a normal integer (`Value::Int`), returns associated value. Returns `None`
76    /// otherwise.
77    ///
78    /// In particular, `None` is also returned if `self` is a `Value::Int64`. Use [`as_i64`] to
79    /// handle this case.
80    ///
81    /// [`as_i64`]: #method.as_i64
82    pub fn as_i32(&self) -> Option<i32> {
83        match *self {
84            Value::Int(i) => Some(i),
85            _ => None,
86        }
87    }
88
89    /// If the `Value` is an integer, returns associated value. Returns `None` otherwise.
90    ///
91    /// This works with both `Value::Int` and `Value::Int64`.
92    pub fn as_i64(&self) -> Option<i64> {
93        match *self {
94            Value::Int(i) => Some(i64::from(i)),
95            Value::Int64(i) => Some(i),
96            _ => None,
97        }
98    }
99
100    /// If the `Value` is a boolean, returns associated value. Returns `None` otherwise.
101    pub fn as_bool(&self) -> Option<bool> {
102        match *self {
103            Value::Bool(b) => Some(b),
104            _ => None,
105        }
106    }
107
108    /// If the `Value` is a string, returns associated value. Returns `None` otherwise.
109    pub fn as_str(&self) -> Option<&str> {
110        match *self {
111            Value::String(ref s) => Some(s),
112            _ => None,
113        }
114    }
115
116    /// If the `Value` is a floating point number, returns associated value. Returns `None`
117    /// otherwise.
118    pub fn as_f64(&self) -> Option<f64> {
119        match *self {
120            Value::Double(d) => Some(d),
121            _ => None,
122        }
123    }
124
125    /// If the `Value` is a date/time, returns associated value. Returns `None` otherwise.
126    pub fn as_datetime(&self) -> Option<DateTime> {
127        match *self {
128            Value::DateTime(dt) => Some(dt),
129            _ => None,
130        }
131    }
132
133    /// If the `Value` is base64 binary data, returns associated value. Returns `None` otherwise.
134    pub fn as_bytes(&self) -> Option<&[u8]> {
135        match *self {
136            Value::Base64(ref data) => Some(data),
137            _ => None,
138        }
139    }
140
141    /// If the `Value` is a struct, returns associated map. Returns `None` otherwise.
142    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
143        match *self {
144            Value::Struct(ref map) => Some(map),
145            _ => None,
146        }
147    }
148
149    /// If the `Value` is an array, returns associated slice. Returns `None` otherwise.
150    pub fn as_array(&self) -> Option<&[Value]> {
151        match *self {
152            Value::Array(ref array) => Some(array),
153            _ => None,
154        }
155    }
156}
157
158// Conversions into and from Value
159
160impl From<i32> for Value {
161    fn from(other: i32) -> Self {
162        Value::Int(other)
163    }
164}
165
166impl<'a> TryFrom<&'a Value> for i32 {
167    type Error = ();
168    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
169        match value {
170            Value::Int(i) => Ok(*i),
171            _ => Err(()),
172        }
173    }
174}
175
176impl From<i64> for Value {
177    fn from(other: i64) -> Self {
178        Value::Int64(other)
179    }
180}
181
182impl<'a> TryFrom<&'a Value> for &'a i64 {
183    type Error = ();
184    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
185        match value {
186            Value::Int64(i) => Ok(i),
187            _ => Err(()),
188        }
189    }
190}
191
192impl From<bool> for Value {
193    fn from(other: bool) -> Self {
194        Value::Bool(other)
195    }
196}
197
198impl<'a> TryFrom<&'a Value> for &'a bool {
199    type Error = ();
200    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
201        match value {
202            Value::Bool(i) => Ok(i),
203            _ => Err(()),
204        }
205    }
206}
207
208impl From<String> for Value {
209    fn from(other: String) -> Self {
210        Value::String(other)
211    }
212}
213
214impl<'a> TryFrom<&'a Value> for String {
215    type Error = ();
216
217    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
218        if let Some(val) = value.as_str() {
219            Ok(val.to_string())
220        } else {
221            Err(())
222        }
223    }
224}
225
226impl From<&str> for Value {
227    fn from(other: &str) -> Self {
228        Value::String(other.to_string())
229    }
230}
231
232impl<'a> TryFrom<&'a Value> for &'a str {
233    type Error = ();
234
235    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
236        if let Some(val) = value.as_str() {
237            Ok(val)
238        } else {
239            Err(())
240        }
241    }
242}
243
244impl From<f64> for Value {
245    fn from(other: f64) -> Self {
246        Value::Double(other)
247    }
248}
249
250impl<'a> TryFrom<&'a Value> for &'a f64 {
251    type Error = ();
252    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
253        match value {
254            Value::Double(i) => Ok(i),
255            _ => Err(()),
256        }
257    }
258}
259
260impl From<DateTime> for Value {
261    fn from(other: DateTime) -> Self {
262        Value::DateTime(other)
263    }
264}
265
266impl<'a> TryFrom<&'a Value> for &'a DateTime {
267    type Error = ();
268    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
269        match value {
270            Value::DateTime(i) => Ok(i),
271            _ => Err(()),
272        }
273    }
274}
275
276impl From<Vec<Value>> for Value {
277    fn from(other: Vec<Value>) -> Value {
278        Value::Array(other)
279    }
280}
281
282impl<'a> TryFrom<&'a Value> for &'a Vec<Value> {
283    type Error = ();
284    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
285        match value {
286            Value::Array(i) => Ok(i),
287            _ => Err(()),
288        }
289    }
290}
291
292impl From<BTreeMap<String, Value>> for Value {
293    fn from(other: BTreeMap<String, Value>) -> Value {
294        Value::Struct(other)
295    }
296}
297
298impl<'a> TryFrom<&'a Value> for &'a BTreeMap<String, Value> {
299    type Error = ();
300    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
301        match value {
302            Value::Struct(i) => Ok(i),
303            _ => Err(()),
304        }
305    }
306}
307
308impl From<Vec<u8>> for Value {
309    fn from(other: Vec<u8>) -> Self {
310        Value::Base64(other)
311    }
312}
313
314impl<'a> TryFrom<&'a Value> for &'a Vec<u8> {
315    type Error = ();
316    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
317        match value {
318            Value::Base64(i) => Ok(i),
319            _ => Err(()),
320        }
321    }
322}