improv_core_model/
value.rs1use crate::ids::MeasureId;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9pub enum ValueType {
10 Number,
11 Boolean,
12 Text,
13 DateTime,
14 Enum,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20pub enum Value {
21 Number(f64),
22 Boolean(bool),
23 Text(String),
24 DateTime(chrono::DateTime<chrono::Utc>),
25 Enum(u32),
27 Error(ValueError),
28}
29
30impl Value {
31 pub fn type_of(&self) -> Option<ValueType> {
32 match self {
33 Value::Number(_) => Some(ValueType::Number),
34 Value::Boolean(_) => Some(ValueType::Boolean),
35 Value::Text(_) => Some(ValueType::Text),
36 Value::DateTime(_) => Some(ValueType::DateTime),
37 Value::Enum(_) => Some(ValueType::Enum),
38 Value::Error(_) => None,
39 }
40 }
41
42 pub fn is_error(&self) -> bool {
43 matches!(self, Value::Error(_))
44 }
45
46 pub fn as_number(&self) -> Option<f64> {
47 match self {
48 Value::Number(n) => Some(*n),
49 _ => None,
50 }
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62pub enum ValueErrorKind {
63 TypeMismatch,
65 DimensionMismatch,
67 DivisionByZero,
69 MissingInput,
71 Custom(String),
72 Null,
74 Ref,
76 Name,
78 Num,
80 Na,
82}
83
84impl ValueErrorKind {
85 pub fn code(&self) -> &'static str {
88 match self {
89 ValueErrorKind::Null => "#NULL!",
90 ValueErrorKind::DivisionByZero => "#DIV/0!",
91 ValueErrorKind::TypeMismatch => "#VALUE!",
92 ValueErrorKind::Ref => "#REF!",
93 ValueErrorKind::Name => "#NAME?",
94 ValueErrorKind::Num => "#NUM!",
95 ValueErrorKind::Na => "#N/A",
96 _ => "#ERR",
97 }
98 }
99
100 pub fn error_type(&self) -> Option<u8> {
103 Some(match self {
104 ValueErrorKind::Null => 1,
105 ValueErrorKind::DivisionByZero => 2,
106 ValueErrorKind::TypeMismatch => 3,
107 ValueErrorKind::Ref => 4,
108 ValueErrorKind::Name => 5,
109 ValueErrorKind::Num => 6,
110 ValueErrorKind::Na => 7,
111 _ => return None,
112 })
113 }
114
115 pub fn from_error_type(n: u8) -> Option<Self> {
117 Some(match n {
118 1 => ValueErrorKind::Null,
119 2 => ValueErrorKind::DivisionByZero,
120 3 => ValueErrorKind::TypeMismatch,
121 4 => ValueErrorKind::Ref,
122 5 => ValueErrorKind::Name,
123 6 => ValueErrorKind::Num,
124 7 => ValueErrorKind::Na,
125 _ => return None,
126 })
127 }
128
129 pub fn from_code(code: &str) -> Option<Self> {
131 (1..=7)
132 .filter_map(Self::from_error_type)
133 .find(|k| k.code().eq_ignore_ascii_case(code.trim()))
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
139pub struct ValueError {
140 pub kind: ValueErrorKind,
141 pub source_measure: Option<MeasureId>,
142}
143
144impl ValueError {
145 pub fn new(kind: ValueErrorKind) -> Self {
146 ValueError {
147 kind,
148 source_measure: None,
149 }
150 }
151
152 pub fn from_measure(kind: ValueErrorKind, measure: MeasureId) -> Self {
153 ValueError {
154 kind,
155 source_measure: Some(measure),
156 }
157 }
158}
159
160impl From<ValueError> for Value {
161 fn from(e: ValueError) -> Value {
162 Value::Error(e)
163 }
164}