ion_rs/result/
conversion.rs1use crate::{Bytes, Decimal, Int, IonType, Sequence, Str, Struct, Symbol, Timestamp};
2
3use std::fmt;
4use std::marker::PhantomData;
5use thiserror::Error;
6
7pub type ConversionOperationResult<FromType, ToType> =
8 Result<ToType, ConversionOperationError<FromType, ToType>>;
9
10#[derive(Clone, Debug, Error, PartialEq)]
12#[error("Type conversion error; expected a(n) {output_type}, found a(n) {input_type}")]
13pub struct ConversionError {
14 input_type: String,
15 output_type: String,
16}
17
18impl<FromType, ToType> From<ConversionOperationError<FromType, ToType>> for ConversionError
19where
20 FromType: ValueTypeExpectation,
21 ToType: TypeExpectation,
22{
23 fn from(err: ConversionOperationError<FromType, ToType>) -> Self {
24 ConversionError {
25 input_type: err.input_value.expected_type_name(),
26 output_type: ToType::expected_type_name(),
27 }
28 }
29}
30
31#[derive(Clone, Debug, PartialEq)]
34pub struct ConversionOperationError<FromType, ToType> {
35 input_value: FromType,
36 output_type: PhantomData<ToType>,
37}
38
39impl<FromType, ToType> fmt::Display for ConversionOperationError<FromType, ToType>
40where
41 FromType: ValueTypeExpectation,
42 ToType: TypeExpectation,
43{
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(
46 f,
47 "Type conversion error; expected a(n) {}, found a(n) {}",
48 ToType::expected_type_name(),
49 self.input_value.expected_type_name()
50 )
51 }
52}
53
54impl<FromType, ToType> std::error::Error for ConversionOperationError<FromType, ToType>
55where
56 FromType: ValueTypeExpectation + fmt::Debug,
57 ToType: TypeExpectation + fmt::Debug,
58{
59}
60
61impl<FromType, ToType> ConversionOperationError<FromType, ToType> {
62 pub fn new(input_value: FromType) -> Self {
63 Self {
64 input_value,
65 output_type: PhantomData,
66 }
67 }
68
69 pub fn original_value(self) -> FromType {
70 self.input_value
71 }
72}
73
74impl<FromType, ToType> From<FromType> for ConversionOperationError<FromType, ToType>
75where
76 FromType: ValueTypeExpectation,
77 ToType: TypeExpectation,
78{
79 fn from(input_value: FromType) -> Self {
80 Self::new(input_value)
81 }
82}
83
84pub trait IonTypeExpectation {
85 fn ion_type(&self) -> IonType;
86}
87
88pub trait ValueTypeExpectation {
89 fn expected_type_name(&self) -> String;
90}
91
92pub trait TypeExpectation {
93 fn expected_type_name() -> String;
94}
95
96macro_rules! impl_type_expectation {
97 ($ty:ty, $e:expr) => {
98 impl TypeExpectation for $ty {
99 fn expected_type_name() -> String {
100 $e.to_string()
101 }
102 }
103 };
104}
105
106macro_rules! impl_type_and_ref_expectation {
107 ($ty:ty, $e:expr) => {
108 impl_type_expectation!($ty, $e);
109 impl_type_expectation!(&$ty, $e);
110 };
111}
112
113impl_type_and_ref_expectation!(Int, IonType::Int);
114impl_type_expectation!(i64, "i64 value");
115impl_type_expectation!(usize, "usize value");
116impl_type_expectation!(f64, IonType::Float);
117impl_type_and_ref_expectation!(Decimal, IonType::Decimal);
118impl_type_and_ref_expectation!(Timestamp, IonType::Timestamp);
119impl_type_and_ref_expectation!(String, "text value");
120impl_type_expectation!(&str, "text value");
121impl_type_and_ref_expectation!(Str, IonType::String);
122impl_type_and_ref_expectation!(Symbol, IonType::Symbol);
123impl_type_expectation!(bool, IonType::Bool);
124impl_type_and_ref_expectation!(Bytes, "lob value");
125impl_type_expectation!(&[u8], "lob value");
126impl_type_and_ref_expectation!(Sequence, "sequence value");
127impl_type_and_ref_expectation!(Struct, IonType::Struct);
128
129impl<T> ValueTypeExpectation for T
130where
131 T: IonTypeExpectation,
132{
133 fn expected_type_name(&self) -> String {
134 self.ion_type().to_string()
135 }
136}