1
0
dust/src/value/map.rs

126 lines
3.2 KiB
Rust
Raw Normal View History

2024-01-28 18:30:57 +00:00
use stanza::{
renderer::{console::Console, Renderer},
style::{HAlign, Styles},
table::{Row, Table},
};
2023-08-22 15:40:50 +00:00
use std::{
collections::BTreeMap,
fmt::{self, Display, Formatter},
2024-02-12 20:07:41 +00:00
sync::{Arc, RwLock, RwLockReadGuard},
2023-08-22 15:40:50 +00:00
};
2024-02-12 20:07:41 +00:00
use crate::{error::rw_lock_error::RwLockError, value::Value};
2023-08-22 15:40:50 +00:00
2023-08-24 04:26:37 +00:00
/// A collection dust variables comprised of key-value pairs.
///
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
/// to one another.
2024-02-12 20:07:41 +00:00
#[derive(Clone, Debug)]
2023-10-25 20:44:50 +00:00
pub struct Map {
2024-02-12 20:07:41 +00:00
inner: Arc<RwLock<BTreeMap<String, Value>>>,
2023-08-22 15:40:50 +00:00
}
2023-10-25 20:44:50 +00:00
impl Map {
2023-08-22 15:40:50 +00:00
/// Creates a new instace.
pub fn new() -> Self {
2023-10-25 20:44:50 +00:00
Map {
2024-02-12 20:07:41 +00:00
inner: Arc::new(RwLock::new(BTreeMap::new())),
2023-08-22 15:40:50 +00:00
}
}
2024-02-11 01:50:49 +00:00
pub fn with_values(variables: BTreeMap<String, Value>) -> Self {
2024-02-12 20:07:41 +00:00
Map {
inner: Arc::new(RwLock::new(variables)),
}
}
2024-02-12 20:07:41 +00:00
pub fn inner(&self) -> Result<RwLockReadGuard<BTreeMap<String, Value>>, RwLockError> {
Ok(self.inner.read()?)
2024-01-17 15:21:00 +00:00
}
2024-02-12 20:07:41 +00:00
pub fn get(&self, key: &str) -> Result<Option<Value>, RwLockError> {
Ok(self.inner()?.get(key).cloned())
2023-08-22 15:40:50 +00:00
}
2024-02-12 20:07:41 +00:00
pub fn set(&self, key: String, value: Value) -> Result<(), RwLockError> {
self.inner.write()?.insert(key, value);
2024-02-12 20:07:41 +00:00
Ok(())
}
2024-01-28 18:30:57 +00:00
pub fn as_text_table(&self) -> Table {
let mut table = Table::with_styles(Styles::default().with(HAlign::Centred));
2024-02-12 20:07:41 +00:00
for (key, value) in self.inner().unwrap().iter() {
2024-01-28 18:30:57 +00:00
if let Value::Map(map) = value {
table.push_row(Row::new(
Styles::default(),
2024-02-11 01:50:49 +00:00
vec![
key.into(),
map.as_text_table().into(),
"".to_string().into(),
],
2024-01-28 18:30:57 +00:00
));
} else if let Value::List(list) = value {
table.push_row(Row::new(
Styles::default(),
2024-02-11 01:50:49 +00:00
vec![key.into(), list.as_text_table().into()],
2024-01-28 18:30:57 +00:00
));
} else {
2024-02-11 01:50:49 +00:00
table.push_row([key, &value.to_string()]);
2024-01-28 18:30:57 +00:00
};
}
if table.is_empty() {
table.push_row(vec!["", "empty map", ""])
}
table
}
2023-08-22 15:40:50 +00:00
}
2023-10-25 20:44:50 +00:00
impl Default for Map {
2023-08-22 15:40:50 +00:00
fn default() -> Self {
Self::new()
}
}
2023-10-25 20:44:50 +00:00
impl Display for Map {
2023-08-22 15:40:50 +00:00
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2024-01-28 18:30:57 +00:00
let renderer = Console::default();
2023-10-26 20:00:06 +00:00
2024-01-28 18:30:57 +00:00
f.write_str(&renderer.render(&self.as_text_table()))
2023-08-22 15:40:50 +00:00
}
}
2024-02-12 20:07:41 +00:00
impl Eq for Map {}
impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool {
let left = self.inner().unwrap();
let right = other.inner().unwrap();
if left.len() != right.len() {
return false;
}
left.iter()
.zip(right.iter())
.all(|((left_key, left_value), (right_key, right_value))| {
left_key == right_key && left_value == right_value
})
}
}
impl PartialOrd for Map {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Map {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.inner().unwrap().cmp(&other.inner().unwrap())
}
}