ion_binary_rs/
ion_value_impl.rs

1use crate::{IonExtractionError, IonParserError, IonValue, NullIonValue, SerdeJsonParseError};
2use bigdecimal::BigDecimal;
3use chrono::{DateTime, FixedOffset, Utc};
4use num_bigint::{BigInt, BigUint};
5use std::collections::HashMap;
6use std::convert::{TryFrom, TryInto};
7
8use serde_json::Value;
9use IonParserError::ValueExtractionFailure;
10
11impl TryFrom<IonValue> for std::collections::HashMap<String, IonValue> {
12    type Error = IonParserError;
13    fn try_from(value: IonValue) -> Result<Self, Self::Error> {
14        match value {
15            IonValue::Struct(value) => Ok(value),
16            _ => Err(ValueExtractionFailure(
17                IonExtractionError::TypeNotSupported(value),
18            )),
19        }
20    }
21}
22
23impl TryFrom<IonValue> for String {
24    type Error = IonParserError;
25
26    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
27        match value {
28            IonValue::String(value) | IonValue::Symbol(value) => Ok(value),
29            _ => Err(ValueExtractionFailure(
30                IonExtractionError::TypeNotSupported(value),
31            )),
32        }
33    }
34}
35
36impl TryFrom<IonValue> for u64 {
37    type Error = IonParserError;
38
39    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
40        match value {
41            IonValue::Integer(value) => value.try_into().map_err(|e| {
42                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
43            }),
44            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
45                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
46            }),
47            _ => Err(ValueExtractionFailure(
48                IonExtractionError::TypeNotSupported(value),
49            )),
50        }
51    }
52}
53
54impl TryFrom<IonValue> for i64 {
55    type Error = IonParserError;
56
57    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
58        match value {
59            IonValue::Integer(value) => Ok(value),
60            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
61                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
62            }),
63            _ => Err(ValueExtractionFailure(
64                IonExtractionError::TypeNotSupported(value),
65            )),
66        }
67    }
68}
69
70impl TryFrom<IonValue> for u32 {
71    type Error = IonParserError;
72
73    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
74        match value {
75            IonValue::Integer(value) => value.try_into().map_err(|e| {
76                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
77            }),
78            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
79                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
80            }),
81            _ => Err(ValueExtractionFailure(
82                IonExtractionError::TypeNotSupported(value),
83            )),
84        }
85    }
86}
87
88impl TryFrom<IonValue> for i32 {
89    type Error = IonParserError;
90
91    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
92        match value {
93            IonValue::Integer(value) => value.try_into().map_err(|e| {
94                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
95            }),
96            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
97                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
98            }),
99            _ => Err(ValueExtractionFailure(
100                IonExtractionError::TypeNotSupported(value),
101            )),
102        }
103    }
104}
105
106impl TryFrom<IonValue> for BigUint {
107    type Error = IonParserError;
108
109    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
110        match value {
111            IonValue::Integer(value) => value.try_into().map_err(|e| {
112                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
113            }),
114            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
115                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
116            }),
117            _ => Err(ValueExtractionFailure(
118                IonExtractionError::TypeNotSupported(value),
119            )),
120        }
121    }
122}
123
124impl TryFrom<IonValue> for BigInt {
125    type Error = IonParserError;
126
127    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
128        match value {
129            IonValue::Integer(value) => Ok(BigInt::from(value)),
130            IonValue::BigInteger(value) => Ok(value),
131            _ => Err(ValueExtractionFailure(
132                IonExtractionError::TypeNotSupported(value),
133            )),
134        }
135    }
136}
137
138impl TryFrom<IonValue> for BigDecimal {
139    type Error = IonParserError;
140
141    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
142        match value {
143            IonValue::Decimal(value) => Ok(value),
144            IonValue::Integer(value) => Ok(BigDecimal::from(value)),
145            IonValue::BigInteger(value) => {
146                let value = BigInt::from_signed_bytes_le(&value.to_signed_bytes_le());
147                Ok(BigDecimal::from(value))
148            }
149            _ => Err(ValueExtractionFailure(
150                IonExtractionError::TypeNotSupported(value),
151            )),
152        }
153    }
154}
155
156impl TryFrom<IonValue> for f64 {
157    type Error = IonParserError;
158
159    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
160        match value {
161            IonValue::Integer(value) => Ok(value as f64),
162            IonValue::BigInteger(value) => i64::try_from(value)
163                .map_err(|e| {
164                    ValueExtractionFailure(IonExtractionError::NumericTransformationError(
165                        Box::new(e),
166                    ))
167                })
168                .map(|value| value as f64),
169            IonValue::Float(value) => Ok(value),
170            _ => Err(ValueExtractionFailure(
171                IonExtractionError::TypeNotSupported(value),
172            )),
173        }
174    }
175}
176
177impl TryFrom<IonValue> for f32 {
178    type Error = IonParserError;
179
180    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
181        match value {
182            IonValue::Integer(value) => Ok(value as f32),
183            IonValue::BigInteger(value) => i64::try_from(value)
184                .map_err(|e| {
185                    ValueExtractionFailure(IonExtractionError::NumericTransformationError(
186                        Box::new(e),
187                    ))
188                })
189                .map(|value| value as f32),
190            IonValue::Float(value) => Ok(value as f32),
191            _ => Err(ValueExtractionFailure(
192                IonExtractionError::TypeNotSupported(value),
193            )),
194        }
195    }
196}
197
198impl TryFrom<IonValue> for DateTime<Utc> {
199    type Error = IonParserError;
200
201    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
202        match value {
203            IonValue::DateTime(value) => Ok(value.with_timezone(&Utc)),
204            _ => Err(ValueExtractionFailure(
205                IonExtractionError::TypeNotSupported(value),
206            )),
207        }
208    }
209}
210
211impl TryFrom<IonValue> for DateTime<FixedOffset> {
212    type Error = IonParserError;
213
214    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
215        match value {
216            IonValue::DateTime(value) => Ok(value),
217            _ => Err(ValueExtractionFailure(
218                IonExtractionError::TypeNotSupported(value),
219            )),
220        }
221    }
222}
223
224impl TryFrom<IonValue> for bool {
225    type Error = IonParserError;
226
227    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
228        match value {
229            IonValue::Bool(value) => Ok(value),
230            _ => Err(ValueExtractionFailure(
231                IonExtractionError::TypeNotSupported(value),
232            )),
233        }
234    }
235}
236
237impl TryFrom<IonValue> for Vec<u8> {
238    type Error = IonParserError;
239
240    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
241        match value {
242            IonValue::Clob(value) => Ok(value),
243            IonValue::Blob(value) => Ok(value),
244            _ => Err(ValueExtractionFailure(
245                IonExtractionError::TypeNotSupported(value),
246            )),
247        }
248    }
249}
250
251impl TryFrom<IonValue> for serde_json::Value {
252    type Error = IonParserError;
253
254    fn try_from(value: IonValue) -> Result<Self, IonParserError> {
255        match value {
256            IonValue::Null(_) => Ok(Value::Null),
257            IonValue::Bool(value) => Ok(Value::Bool(value)),
258            IonValue::Integer(value) => {
259                let json_number = serde_json::Number::from(value);
260                Ok(Value::from(json_number))
261            }
262            IonValue::BigInteger(value) => Ok(Value::Number(i64::try_from(value)?.into())),
263            ion_value @ IonValue::Decimal(_) => {
264                let number = f64::try_from(ion_value)?;
265
266                let json_number = serde_json::Number::from_f64(number)
267                    .ok_or(IonParserError::DecimalNotANumericValue(number))?;
268
269                Ok(Value::Number(json_number))
270            }
271            IonValue::Float(value) => {
272                let json_number = serde_json::Number::from_f64(value)
273                    .ok_or(IonParserError::DecimalNotANumericValue(value))?;
274
275                Ok(Value::from(json_number))
276            }
277            IonValue::String(value) => Ok(Value::String(value)),
278            IonValue::List(vector) => Ok(Value::Array(
279                vector
280                    .into_iter()
281                    .map(|element| element.try_into())
282                    .collect::<Result<Vec<Value>, _>>()?,
283            )),
284            IonValue::Struct(values) => {
285                let mut result_map = serde_json::Map::with_capacity(values.len());
286
287                for (key, ion_value) in values {
288                    result_map.insert(key.to_string(), Value::try_from(ion_value)?);
289                }
290                Ok(Value::Object(result_map))
291            }
292            _ => Err(IonParserError::TypeNotSupported(value)),
293        }
294    }
295}
296
297impl TryFrom<&IonValue> for Vec<IonValue> {
298    type Error = IonParserError;
299
300    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
301        match value {
302            IonValue::List(value) => Ok(value.to_vec()),
303            IonValue::SExpr(value) => Ok(value.to_vec()),
304            _ => Err(ValueExtractionFailure(
305                IonExtractionError::TypeNotSupported(value.clone()),
306            )),
307        }
308    }
309}
310
311impl TryFrom<&IonValue> for HashMap<String, IonValue> {
312    type Error = ();
313    fn try_from(value: &IonValue) -> Result<Self, Self::Error> {
314        if let IonValue::Struct(value) = value {
315            Ok(value.clone())
316        } else {
317            Err(())
318        }
319    }
320}
321
322impl TryFrom<&IonValue> for String {
323    type Error = IonParserError;
324
325    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
326        match value {
327            IonValue::String(value) | IonValue::Symbol(value) => Ok(value.clone()),
328            _ => Err(ValueExtractionFailure(
329                IonExtractionError::TypeNotSupported(value.clone()),
330            )),
331        }
332    }
333}
334
335impl TryFrom<&IonValue> for u64 {
336    type Error = IonParserError;
337
338    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
339        match value {
340            IonValue::Integer(value) => (*value).try_into().map_err(|e| {
341                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
342            }),
343            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
344                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
345            }),
346            _ => Err(ValueExtractionFailure(
347                IonExtractionError::TypeNotSupported(value.clone()),
348            )),
349        }
350    }
351}
352
353impl TryFrom<&IonValue> for i64 {
354    type Error = IonParserError;
355
356    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
357        match value {
358            IonValue::Integer(value) => Ok(*value),
359            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
360                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
361            }),
362            _ => Err(ValueExtractionFailure(
363                IonExtractionError::TypeNotSupported(value.clone()),
364            )),
365        }
366    }
367}
368
369impl TryFrom<&IonValue> for u32 {
370    type Error = IonParserError;
371
372    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
373        match value {
374            IonValue::Integer(value) => (*value).try_into().map_err(|e| {
375                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
376            }),
377            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
378                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
379            }),
380            _ => Err(ValueExtractionFailure(
381                IonExtractionError::TypeNotSupported(value.clone()),
382            )),
383        }
384    }
385}
386
387impl TryFrom<&IonValue> for i32 {
388    type Error = IonParserError;
389
390    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
391        match value {
392            IonValue::Integer(value) => (*value).try_into().map_err(|e| {
393                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
394            }),
395            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
396                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
397            }),
398            _ => Err(ValueExtractionFailure(
399                IonExtractionError::TypeNotSupported(value.clone()),
400            )),
401        }
402    }
403}
404
405impl TryFrom<&IonValue> for BigUint {
406    type Error = IonParserError;
407
408    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
409        match value {
410            IonValue::Integer(value) => (*value).try_into().map_err(|e| {
411                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
412            }),
413            IonValue::BigInteger(value) => value.try_into().map_err(|e| {
414                ValueExtractionFailure(IonExtractionError::NumericTransformationError(Box::new(e)))
415            }),
416            _ => Err(ValueExtractionFailure(
417                IonExtractionError::TypeNotSupported(value.clone()),
418            )),
419        }
420    }
421}
422
423impl TryFrom<&IonValue> for BigInt {
424    type Error = IonParserError;
425
426    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
427        match value {
428            IonValue::Integer(value) => Ok(BigInt::from(*value)),
429            IonValue::BigInteger(value) => Ok(value.clone()),
430            _ => Err(ValueExtractionFailure(
431                IonExtractionError::TypeNotSupported(value.clone()),
432            )),
433        }
434    }
435}
436
437impl TryFrom<&IonValue> for f64 {
438    type Error = IonParserError;
439
440    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
441        match value {
442            IonValue::Integer(value) => Ok(*value as f64),
443            IonValue::BigInteger(value) => i64::try_from(value)
444                .map_err(|e| {
445                    ValueExtractionFailure(IonExtractionError::NumericTransformationError(
446                        Box::new(e),
447                    ))
448                })
449                .map(|value| value as f64),
450            IonValue::Float(value) => Ok(*value),
451            _ => Err(ValueExtractionFailure(
452                IonExtractionError::TypeNotSupported(value.clone()),
453            )),
454        }
455    }
456}
457
458impl TryFrom<&IonValue> for f32 {
459    type Error = IonParserError;
460
461    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
462        match value {
463            IonValue::Integer(value) => Ok(*value as f32),
464            IonValue::BigInteger(value) => i64::try_from(value)
465                .map_err(|e| {
466                    ValueExtractionFailure(IonExtractionError::NumericTransformationError(
467                        Box::new(e),
468                    ))
469                })
470                .map(|value| value as f32),
471            IonValue::Float(value) => Ok(*value as f32),
472            _ => Err(ValueExtractionFailure(
473                IonExtractionError::TypeNotSupported(value.clone()),
474            )),
475        }
476    }
477}
478
479impl TryFrom<&IonValue> for DateTime<Utc> {
480    type Error = IonParserError;
481
482    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
483        match value {
484            IonValue::DateTime(value) => Ok(value.with_timezone(&Utc)),
485            _ => Err(ValueExtractionFailure(
486                IonExtractionError::TypeNotSupported(value.clone()),
487            )),
488        }
489    }
490}
491
492impl TryFrom<&IonValue> for DateTime<FixedOffset> {
493    type Error = IonParserError;
494
495    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
496        match value {
497            IonValue::DateTime(value) => Ok(*value),
498            _ => Err(ValueExtractionFailure(
499                IonExtractionError::TypeNotSupported(value.clone()),
500            )),
501        }
502    }
503}
504
505impl TryFrom<&IonValue> for bool {
506    type Error = IonParserError;
507
508    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
509        match value {
510            IonValue::Bool(value) => Ok(*value),
511            _ => Err(ValueExtractionFailure(
512                IonExtractionError::TypeNotSupported(value.clone()),
513            )),
514        }
515    }
516}
517
518impl TryFrom<&IonValue> for Vec<u8> {
519    type Error = IonParserError;
520
521    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
522        match value {
523            IonValue::Clob(value) => Ok(value.to_vec()),
524            IonValue::Blob(value) => Ok(value.to_vec()),
525            _ => Err(ValueExtractionFailure(
526                IonExtractionError::TypeNotSupported(value.clone()),
527            )),
528        }
529    }
530}
531
532impl TryFrom<&IonValue> for serde_json::Value {
533    type Error = IonParserError;
534
535    fn try_from(value: &IonValue) -> Result<Self, IonParserError> {
536        value.clone().try_into()
537    }
538}
539
540impl From<String> for IonValue {
541    fn from(value: String) -> IonValue {
542        IonValue::String(value)
543    }
544}
545
546impl From<&str> for IonValue {
547    fn from(value: &str) -> IonValue {
548        IonValue::String(value.to_string())
549    }
550}
551
552impl From<u16> for IonValue {
553    fn from(value: u16) -> IonValue {
554        IonValue::Integer(value.into())
555    }
556}
557
558impl From<i16> for IonValue {
559    fn from(value: i16) -> IonValue {
560        IonValue::Integer(value.into())
561    }
562}
563
564impl From<u32> for IonValue {
565    fn from(value: u32) -> IonValue {
566        IonValue::Integer(value.into())
567    }
568}
569
570impl From<i32> for IonValue {
571    fn from(value: i32) -> IonValue {
572        IonValue::Integer(value.into())
573    }
574}
575
576impl From<u64> for IonValue {
577    fn from(value: u64) -> IonValue {
578        match i64::try_from(value) {
579            Ok(value) => IonValue::Integer(value),
580            Err(_) => IonValue::BigInteger(BigInt::from(value)),
581        }
582    }
583}
584
585impl From<i64> for IonValue {
586    fn from(value: i64) -> IonValue {
587        IonValue::Integer(value)
588    }
589}
590
591impl From<u128> for IonValue {
592    fn from(value: u128) -> IonValue {
593        IonValue::BigInteger(BigInt::from(value))
594    }
595}
596
597impl From<i128> for IonValue {
598    fn from(value: i128) -> IonValue {
599        IonValue::BigInteger(BigInt::from(value))
600    }
601}
602
603impl From<BigInt> for IonValue {
604    fn from(value: BigInt) -> IonValue {
605        IonValue::BigInteger(value)
606    }
607}
608
609impl From<BigUint> for IonValue {
610    fn from(value: BigUint) -> IonValue {
611        IonValue::BigInteger(BigInt::from(value))
612    }
613}
614
615impl From<DateTime<FixedOffset>> for IonValue {
616    fn from(value: DateTime<FixedOffset>) -> IonValue {
617        IonValue::DateTime(value)
618    }
619}
620
621impl From<DateTime<Utc>> for IonValue {
622    fn from(value: DateTime<Utc>) -> IonValue {
623        IonValue::DateTime(value.into())
624    }
625}
626
627impl From<bool> for IonValue {
628    fn from(value: bool) -> IonValue {
629        IonValue::Bool(value)
630    }
631}
632
633impl From<Vec<u8>> for IonValue {
634    fn from(value: Vec<u8>) -> IonValue {
635        IonValue::Blob(value)
636    }
637}
638
639impl From<&[u8]> for IonValue {
640    fn from(value: &[u8]) -> IonValue {
641        IonValue::Blob(value.to_vec())
642    }
643}
644
645impl From<f32> for IonValue {
646    fn from(value: f32) -> IonValue {
647        IonValue::Float(value.into())
648    }
649}
650
651impl From<f64> for IonValue {
652    fn from(value: f64) -> IonValue {
653        IonValue::Float(value)
654    }
655}
656
657impl From<BigDecimal> for IonValue {
658    fn from(value: BigDecimal) -> IonValue {
659        IonValue::Decimal(value)
660    }
661}
662
663impl<I: Into<IonValue>> From<Vec<I>> for IonValue {
664    fn from(values: Vec<I>) -> Self {
665        let mut vec: Vec<IonValue> = vec![];
666
667        for value in values {
668            vec.push(value.into())
669        }
670
671        IonValue::List(vec)
672    }
673}
674
675impl<I: Into<IonValue> + Clone> From<&[I]> for IonValue {
676    fn from(values: &[I]) -> Self {
677        let mut vec: Vec<IonValue> = vec![];
678
679        for value in values.iter().cloned() {
680            vec.push(value.into())
681        }
682
683        IonValue::List(vec)
684    }
685}
686
687impl<I: Into<IonValue>, K: Into<String>> From<HashMap<K, I>> for IonValue {
688    fn from(values: HashMap<K, I>) -> Self {
689        let mut vec: HashMap<String, IonValue> = HashMap::new();
690
691        for (key, value) in values.into_iter() {
692            vec.insert(key.into(), value.into());
693        }
694
695        IonValue::Struct(vec)
696    }
697}
698
699impl<I: Into<IonValue> + Clone> From<&I> for IonValue {
700    fn from(value: &I) -> IonValue {
701        value.clone().into()
702    }
703}
704
705impl TryFrom<serde_json::Value> for IonValue {
706    type Error = SerdeJsonParseError;
707
708    fn try_from(value: serde_json::Value) -> Result<IonValue, SerdeJsonParseError> {
709        match value {
710            serde_json::Value::Null => Ok(IonValue::Null(NullIonValue::Null)),
711            serde_json::Value::Bool(bool) => Ok(bool.into()),
712            serde_json::Value::Number(number) => {
713                if number.is_f64() {
714                    number
715                        .as_f64()
716                        .ok_or(SerdeJsonParseError::WrongNumberType)
717                        .map(Into::into)
718                } else if number.is_i64() {
719                    number
720                        .as_i64()
721                        .ok_or(SerdeJsonParseError::WrongNumberType)
722                        .map(Into::into)
723                } else if number.is_u64() {
724                    number
725                        .as_u64()
726                        .ok_or(SerdeJsonParseError::WrongNumberType)
727                        .map(Into::into)
728                } else {
729                    Err(SerdeJsonParseError::NonExistentNumberType)
730                }
731            }
732            serde_json::Value::String(string) => Ok(string.into()),
733            serde_json::Value::Array(array) => {
734                let list: Result<Vec<IonValue>, SerdeJsonParseError> = array
735                    .into_iter()
736                    .map(|element| element.try_into())
737                    .collect();
738                match list {
739                    Ok(list) => Ok(list.into()),
740                    Err(error) => Err(error),
741                }
742            }
743            serde_json::Value::Object(map) => {
744                let mut hash_map = HashMap::<String, IonValue>::new();
745                for (key, value) in map.into_iter() {
746                    let ion_value = value.try_into()?;
747                    hash_map.insert(key.to_string(), ion_value);
748                }
749                Ok(hash_map.into())
750            }
751        }
752    }
753}