microcad_lang/model/
properties.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Object properties.
5
6use crate::{syntax::*, tree_display::*, value::*};
7use derive_more::{Deref, DerefMut};
8use std::collections::BTreeMap;
9
10/// A list of object properties.
11///
12/// It is required that properties are always sorted by their id.
13#[derive(Clone, Default, Debug, Deref, DerefMut)]
14pub struct Properties(BTreeMap<Identifier, Value>);
15
16impl FromIterator<(Identifier, Value)> for Properties {
17    fn from_iter<T: IntoIterator<Item = (Identifier, Value)>>(iter: T) -> Self {
18        Self(iter.into_iter().collect())
19    }
20}
21
22impl Properties {
23    /// Test if each property has a value.
24    pub fn is_valid(&self) -> bool {
25        self.0.iter().all(|(_, value)| !value.is_invalid())
26    }
27}
28
29impl std::fmt::Display for Properties {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        writeln!(f, "Properties:")?;
32        for (id, value) in self.0.iter() {
33            writeln!(f, "\t{id:?} : {value:?}")?;
34        }
35
36        Ok(())
37    }
38}
39
40impl TreeDisplay for Properties {
41    fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
42        if depth.debug {
43            self.iter()
44                .try_for_each(|(id, value)| writeln!(f, "{:depth$}- {id:?} = {value:?}", ""))
45        } else {
46            self.iter()
47                .try_for_each(|(id, value)| writeln!(f, "{:depth$}- {id} = {value}", ""))
48        }
49    }
50}
51
52/// Access a value of a property by id.
53pub trait PropertiesAccess {
54    /// Get a value of property, or [`Value::None`] if the property does not exist.
55    fn get_property(&self, id: &Identifier) -> Option<&Value>;
56    /// Set value of an existing property or add a new property
57    fn set_property(&mut self, id: Identifier, value: Value) -> Option<Value>;
58    /// Get all properties
59    fn get_properties(&self) -> Option<&Properties>;
60    /// Set or create properties with the given ids and values.
61    fn add_properties(&mut self, props: Properties);
62}