coda_api/ext/
parse_cell_value.rs1use crate::types::{CellValue, RichSingleValue, RichValue, ScalarValue, Value, ValueVariant0};
2use thiserror::Error;
3
4impl TryFrom<CellValue> for String {
5 type Error = ConvertCellValueToStringError;
6
7 fn try_from(cell_value: CellValue) -> Result<Self, Self::Error> {
8 use ConvertCellValueToStringError::*;
9 match cell_value {
10 CellValue::Value(Value::Variant0(ValueVariant0::Variant0(value))) => Ok(value),
11 CellValue::RichValue(RichValue::Variant0(RichSingleValue::ScalarValue(ScalarValue::Variant0(value)))) => Ok(value),
12 cell_value => Err(InvalidCellValue {
13 cell_value,
14 }),
15 }
16 }
17}
18
19impl TryFrom<CellValue> for f64 {
20 type Error = ConvertCellValueToF64Error;
21
22 fn try_from(cell_value: CellValue) -> Result<Self, Self::Error> {
23 use ConvertCellValueToF64Error::*;
24 match cell_value {
25 CellValue::Value(Value::Variant0(ValueVariant0::Variant1(value))) => Ok(value),
26 CellValue::RichValue(RichValue::Variant0(RichSingleValue::ScalarValue(ScalarValue::Variant1(value)))) => Ok(value),
27 cell_value => Err(InvalidCellValue {
28 cell_value,
29 }),
30 }
31 }
32}
33
34impl TryFrom<CellValue> for Option<bool> {
36 type Error = ConvertCellValueToBoolError;
37
38 fn try_from(cell_value: CellValue) -> Result<Self, Self::Error> {
39 use ConvertCellValueToBoolError::*;
40 match cell_value {
41 CellValue::Value(Value::Variant0(ValueVariant0::Variant0(value))) if value.is_empty() => Ok(None),
42 CellValue::Value(Value::Variant0(ValueVariant0::Variant2(value))) => Ok(Some(value)),
43 CellValue::RichValue(RichValue::Variant0(RichSingleValue::ScalarValue(ScalarValue::Variant2(value)))) => Ok(Some(value)),
44 cell_value => Err(InvalidCellValue {
45 cell_value,
46 }),
47 }
48 }
49}
50
51#[cfg(feature = "time")]
52mod time_impls {
53 use super::*;
54 use crate::{DurationValueParserError, parse_duration_value};
55 use errgonomic::handle;
56 use thiserror::Error;
57 use time::format_description::well_known::Rfc3339;
58 use time::{Duration, OffsetDateTime};
59
60 impl TryFrom<CellValue> for Option<OffsetDateTime> {
61 type Error = ConvertCellValueToOptionOffsetDateTimeError;
62
63 fn try_from(value: CellValue) -> Result<Self, Self::Error> {
64 use ConvertCellValueToOptionOffsetDateTimeError::*;
65 let string = handle!(String::try_from(value), ConvertCellValueToStringFailed);
66 if string.is_empty() {
67 Ok(None)
68 } else {
69 let value = handle!(OffsetDateTime::parse(&string, &Rfc3339), OffsetDateTimeParseFailed);
70 Ok(Some(value))
71 }
72 }
73 }
74
75 impl TryFrom<CellValue> for Option<Duration> {
76 type Error = ConvertCellValueToOptionDurationError;
77
78 fn try_from(value: CellValue) -> Result<Self, Self::Error> {
79 use ConvertCellValueToOptionDurationError::{ConvertCellValueToStringFailed, DurationParseFailed};
80
81 let string = handle!(String::try_from(value), ConvertCellValueToStringFailed);
82 Ok(handle!(parse_duration_value(&string), DurationParseFailed))
83 }
84 }
85
86 #[derive(Debug, Error)]
87 pub enum ConvertCellValueToOptionDurationError {
88 #[error("failed to convert cell value to duration string: {source}")]
89 ConvertCellValueToStringFailed {
90 #[source]
91 source: ConvertCellValueToStringError,
92 },
93 #[error("failed to parse duration value: {source}")]
94 DurationParseFailed {
95 #[source]
96 source: DurationValueParserError,
97 },
98 }
99
100 #[derive(Debug, Error)]
101 pub enum ConvertCellValueToOptionOffsetDateTimeError {
102 #[error("failed to convert cell value to timestamp string: {source}")]
103 ConvertCellValueToStringFailed {
104 #[source]
105 source: ConvertCellValueToStringError,
106 },
107 #[error("failed to parse RFC3339 timestamp: {source}")]
108 OffsetDateTimeParseFailed {
109 #[source]
110 source: time::Error,
111 },
112 }
113}
114
115#[cfg(feature = "time")]
116pub use time_impls::*;
117
118#[derive(Debug, Error)]
119pub enum ConvertCellValueToStringError {
120 #[error("cell value is not a string: {cell_value:?}")]
121 InvalidCellValue { cell_value: CellValue },
122}
123
124#[derive(Debug, Error)]
125pub enum ConvertCellValueToF64Error {
126 #[error("cell value is not a number: {cell_value:?}")]
127 InvalidCellValue { cell_value: CellValue },
128}
129
130#[derive(Debug, Error)]
131pub enum ConvertCellValueToBoolError {
132 #[error("cell value is not a boolean: {cell_value:?}")]
133 InvalidCellValue { cell_value: CellValue },
134}
135
136#[derive(Debug, Error)]
137pub enum ConvertCellValueError {
138 #[error("failed to convert cell value to string: {source}")]
139 ConvertCellValueToStringFailed {
140 #[source]
141 source: ConvertCellValueToStringError,
142 },
143 #[error("failed to convert cell value to number: {source}")]
144 ConvertCellValueToF64Failed {
145 #[source]
146 source: ConvertCellValueToF64Error,
147 },
148 #[error("failed to convert cell value to boolean: {source}")]
149 ConvertCellValueToBoolFailed {
150 #[source]
151 source: ConvertCellValueToBoolError,
152 },
153 #[cfg(feature = "time")]
154 #[error("failed to convert cell value to timestamp: {source}")]
155 ConvertCellValueToOffsetDateTimeFailed {
156 #[source]
157 source: ConvertCellValueToOptionOffsetDateTimeError,
158 },
159}