microcad_lang/value/
array.rs1use crate::{ty::*, value::*};
7use derive_more::{Deref, DerefMut};
8
9#[derive(Clone, Debug, Deref, DerefMut)]
11pub struct Array {
12 #[deref]
14 #[deref_mut]
15 items: ValueList,
16 ty: Type,
18}
19
20impl Array {
21 pub fn new(ty: Type) -> Self {
23 Self {
24 items: ValueList::default(),
25 ty,
26 }
27 }
28
29 pub fn from_values(items: ValueList, ty: Type) -> Self {
31 Self { items, ty }
32 }
33}
34
35impl Array {
39 pub fn first(&self) -> Value {
41 self.items.first().cloned().unwrap_or_default()
42 }
43
44 pub fn last(&self) -> Value {
46 self.items.last().cloned().unwrap_or_default()
47 }
48
49 pub fn tail(&self) -> Array {
51 Array::from_values(
52 self.items.iter().skip(1).cloned().collect(),
53 self.ty.clone(),
54 )
55 }
56
57 pub fn rev(&self) -> Array {
59 Array::from_values(self.items.iter().rev().cloned().collect(), self.ty.clone())
60 }
61
62 pub fn sorted(&self) -> Array {
66 let mut items = self.items.clone();
67 match self.ty {
68 Type::Integer | Type::Quantity(..) | Type::String | Type::Bool => {
69 items.sort_by(|a, b| {
70 assert_eq!(a.ty(), b.ty());
71 match (a, b) {
72 (Value::Quantity(a), Value::Quantity(b)) => a.value.total_cmp(&b.value),
73 (Value::Integer(a), Value::Integer(b)) => a.cmp(b),
74 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
75 (Value::String(a), Value::String(b)) => a.cmp(b),
76 _ => unreachable!(),
77 }
78 })
79 }
80 _ => {}
81 };
82
83 Array::from_values(items, self.ty.clone())
84 }
85
86 pub fn all_equal(&self) -> bool {
88 match self.first() {
89 Value::None => true,
90 value => self[1..].iter().all(|x| *x == value),
91 }
92 }
93
94 pub fn is_ascending(&self) -> bool {
96 self.as_slice().windows(2).all(|w| w[0] <= w[1])
97 }
98
99 pub fn is_descending(&self) -> bool {
101 self.as_slice().windows(2).all(|w| w[0] >= w[1])
102 }
103}
104
105impl PartialEq for Array {
106 fn eq(&self, other: &Self) -> bool {
107 self.ty == other.ty && self.items == other.items
108 }
109}
110
111impl IntoIterator for Array {
112 type Item = Value;
113 type IntoIter = std::vec::IntoIter<Self::Item>;
114
115 fn into_iter(self) -> Self::IntoIter {
116 self.items.into_iter()
117 }
118}
119
120impl TryFrom<ValueList> for Array {
121 type Error = ValueError;
122 fn try_from(items: ValueList) -> ValueResult<Array> {
123 match items.types().common_type() {
124 Some(ty) => Ok(Array::from_values(items, ty)),
125 None => Err(ValueError::CommonTypeExpected),
126 }
127 }
128}
129
130impl FromIterator<Value> for Array {
131 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
132 let items: ValueList = iter.into_iter().collect();
133 let ty = items.types().common_type().expect("Common type");
134 Self { ty, items }
135 }
136}
137
138impl std::fmt::Display for Array {
139 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
140 write!(
141 f,
142 "[{items}]",
143 items = self
144 .items
145 .iter()
146 .map(|v| v.to_string())
147 .collect::<Vec<_>>()
148 .join(", ")
149 )
150 }
151}
152
153impl crate::ty::Ty for Array {
154 fn ty(&self) -> Type {
155 Type::Array(Box::new(self.ty.clone()))
156 }
157}
158
159impl std::ops::Add<Value> for Array {
161 type Output = ValueResult;
162
163 fn add(self, rhs: Value) -> Self::Output {
164 if self.ty.is_compatible_to(&rhs.ty()) {
165 Ok(Value::Array(Self::from_values(
166 ValueList::new(
167 self.items
168 .iter()
169 .map(|value| value.clone() + rhs.clone())
170 .collect::<Result<Vec<_>, _>>()?,
171 ),
172 self.ty,
173 )))
174 } else {
175 Err(ValueError::InvalidOperator("+".into()))
176 }
177 }
178}
179
180impl std::ops::Sub<Value> for Array {
182 type Output = ValueResult;
183
184 fn sub(self, rhs: Value) -> Self::Output {
185 if self.ty.is_compatible_to(&rhs.ty()) {
186 Ok(Value::Array(Self::from_values(
187 ValueList::new(
188 self.items
189 .iter()
190 .map(|value| value.clone() - rhs.clone())
191 .collect::<Result<Vec<_>, _>>()?,
192 ),
193 self.ty,
194 )))
195 } else {
196 Err(ValueError::InvalidOperator("-".into()))
197 }
198 }
199}
200
201impl std::ops::Mul<Value> for Array {
203 type Output = ValueResult;
204
205 fn mul(self, rhs: Value) -> Self::Output {
206 match self.ty {
207 Type::Quantity(_) | Type::Integer => Ok(Value::Array(Array::from_values(
209 ValueList::new({
210 self.iter()
211 .map(|value| value.clone() * rhs.clone())
212 .collect::<Result<Vec<_>, _>>()?
213 }),
214 self.ty * rhs.ty().clone(),
215 ))),
216 _ => Err(ValueError::InvalidOperator("*".into())),
217 }
218 }
219}
220
221impl std::ops::Div<Value> for Array {
223 type Output = ValueResult;
224
225 fn div(self, rhs: Value) -> Self::Output {
226 let values = ValueList::new(
227 self.iter()
228 .map(|value| value.clone() / rhs.clone())
229 .collect::<Result<Vec<_>, _>>()?,
230 );
231
232 match (&self.ty, rhs.ty()) {
233 (Type::Integer, Type::Integer) => Ok(Value::Array(Array::from_values(
235 values,
236 self.ty / rhs.ty().clone(),
237 ))),
238 (Type::Quantity(_), _) => Ok(Value::Array(values.try_into()?)),
239 _ => Err(ValueError::InvalidOperator("/".into())),
240 }
241 }
242}
243
244impl std::ops::Neg for Array {
245 type Output = ValueResult;
246
247 fn neg(self) -> Self::Output {
248 let items = ValueList::new(
249 self.iter()
250 .map(|value| -value.clone())
251 .collect::<Result<Vec<_>, _>>()?,
252 );
253 Ok(Value::Array(items.try_into()?))
254 }
255}
256
257impl std::ops::Not for Array {
258 type Output = ValueResult;
259
260 fn not(self) -> Self::Output {
261 let items = ValueList::new(
262 self.iter()
263 .map(|value| !value.clone())
264 .collect::<Result<Vec<_>, _>>()?,
265 );
266 Ok(Value::Array(items.try_into()?))
267 }
268}