microcad_lang/value/
array.rs1use crate::{ty::*, value::*};
7use derive_more::{Deref, DerefMut};
8
9#[derive(Clone, 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 std::fmt::Debug for Array {
154 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
155 write!(
156 f,
157 "[{items}]",
158 items = self
159 .items
160 .iter()
161 .map(|v| format!("{v:?}"))
162 .collect::<Vec<_>>()
163 .join(", ")
164 )
165 }
166}
167
168impl crate::ty::Ty for Array {
169 fn ty(&self) -> Type {
170 Type::Array(Box::new(self.ty.clone()))
171 }
172}
173
174impl std::ops::Add<Value> for Array {
176 type Output = ValueResult;
177
178 fn add(self, rhs: Value) -> Self::Output {
179 if self.ty.is_compatible_to(&rhs.ty()) {
180 Ok(Value::Array(Self::from_values(
181 ValueList::new(
182 self.items
183 .iter()
184 .map(|value| value.clone() + rhs.clone())
185 .collect::<Result<Vec<_>, _>>()?,
186 ),
187 self.ty,
188 )))
189 } else {
190 Err(ValueError::InvalidOperator("+".into()))
191 }
192 }
193}
194
195impl std::ops::Sub<Value> for Array {
197 type Output = ValueResult;
198
199 fn sub(self, rhs: Value) -> Self::Output {
200 if self.ty.is_compatible_to(&rhs.ty()) {
201 Ok(Value::Array(Self::from_values(
202 ValueList::new(
203 self.items
204 .iter()
205 .map(|value| value.clone() - rhs.clone())
206 .collect::<Result<Vec<_>, _>>()?,
207 ),
208 self.ty,
209 )))
210 } else {
211 Err(ValueError::InvalidOperator("-".into()))
212 }
213 }
214}
215
216impl std::ops::Mul<Value> for Array {
218 type Output = ValueResult;
219
220 fn mul(self, rhs: Value) -> Self::Output {
221 match self.ty {
222 Type::Quantity(_) | Type::Integer => Ok(Value::Array(Array::from_values(
224 ValueList::new({
225 self.iter()
226 .map(|value| value.clone() * rhs.clone())
227 .collect::<Result<Vec<_>, _>>()?
228 }),
229 self.ty * rhs.ty().clone(),
230 ))),
231 _ => Err(ValueError::InvalidOperator("*".into())),
232 }
233 }
234}
235
236impl std::ops::Div<Value> for Array {
238 type Output = ValueResult;
239
240 fn div(self, rhs: Value) -> Self::Output {
241 let values = ValueList::new(
242 self.iter()
243 .map(|value| value.clone() / rhs.clone())
244 .collect::<Result<Vec<_>, _>>()?,
245 );
246
247 match (&self.ty, rhs.ty()) {
248 (Type::Integer, Type::Integer) => Ok(Value::Array(Array::from_values(
250 values,
251 self.ty / rhs.ty().clone(),
252 ))),
253 (Type::Quantity(_), _) => Ok(Value::Array(values.try_into()?)),
254 _ => Err(ValueError::InvalidOperator("/".into())),
255 }
256 }
257}
258
259impl std::ops::Neg for Array {
260 type Output = ValueResult;
261
262 fn neg(self) -> Self::Output {
263 let items = ValueList::new(
264 self.iter()
265 .map(|value| -value.clone())
266 .collect::<Result<Vec<_>, _>>()?,
267 );
268 Ok(Value::Array(items.try_into()?))
269 }
270}
271
272impl std::ops::Not for Array {
273 type Output = ValueResult;
274
275 fn not(self) -> Self::Output {
276 let items = ValueList::new(
277 self.iter()
278 .map(|value| !value.clone())
279 .collect::<Result<Vec<_>, _>>()?,
280 );
281 Ok(Value::Array(items.try_into()?))
282 }
283}