dust/src/value/map.rs

234 lines
6.0 KiB
Rust
Raw Normal View History

use serde::{
de::{MapAccess, Visitor},
ser::SerializeMap,
Deserialize, Serialize,
};
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::{
2023-10-26 20:00:06 +00:00
cmp::Ordering,
2023-08-22 15:40:50 +00:00
collections::BTreeMap,
fmt::{self, Display, Formatter},
marker::PhantomData,
2024-01-17 15:21:00 +00:00
sync::{Arc, RwLock, RwLockReadGuard},
2023-08-22 15:40:50 +00:00
};
2024-01-06 08:47:54 +00:00
use crate::{value::Value, Result, Structure, Type};
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.
2023-10-26 20:00:06 +00:00
#[derive(Clone, Debug)]
2023-10-25 20:44:50 +00:00
pub struct Map {
2023-12-09 22:15:41 +00:00
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>,
2024-01-06 08:47:54 +00:00
structure: Option<Structure>,
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 {
2023-10-26 20:00:06 +00:00
variables: Arc::new(RwLock::new(BTreeMap::new())),
2024-01-06 08:47:54 +00:00
structure: None,
2023-08-22 15:40:50 +00:00
}
}
pub fn from_structure(structure: Structure) -> Self {
let mut variables = BTreeMap::new();
for (key, (value_option, r#type)) in structure.inner() {
variables.insert(
key.clone(),
(
value_option.clone().unwrap_or(Value::none()),
r#type.clone(),
),
);
}
Map {
variables: Arc::new(RwLock::new(variables)),
structure: Some(structure),
}
}
2024-01-17 15:21:00 +00:00
pub fn with_variables(variables: BTreeMap<String, (Value, Type)>) -> Self {
Map {
variables: Arc::new(RwLock::new(variables)),
structure: None,
}
}
2023-11-05 18:54:29 +00:00
pub fn clone_from(other: &Self) -> Result<Self> {
2023-10-27 02:35:59 +00:00
let mut new_map = BTreeMap::new();
2023-12-09 22:15:41 +00:00
for (key, (value, r#type)) in other.variables()?.iter() {
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
2023-10-27 02:35:59 +00:00
}
2023-11-05 18:54:29 +00:00
Ok(Map {
2023-10-27 02:35:59 +00:00
variables: Arc::new(RwLock::new(new_map)),
2024-01-06 08:47:54 +00:00
structure: other.structure.clone(),
2023-11-05 18:54:29 +00:00
})
2023-08-22 15:40:50 +00:00
}
2023-12-09 22:15:41 +00:00
pub fn variables(&self) -> Result<RwLockReadGuard<BTreeMap<String, (Value, Type)>>> {
2023-11-05 18:54:29 +00:00
Ok(self.variables.read()?)
2023-08-22 15:40:50 +00:00
}
2024-01-10 01:38:40 +00:00
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
2024-01-13 18:30:50 +00:00
log::info!("Setting variable {key} = {value}");
2024-01-10 01:38:40 +00:00
let value_type = value.r#type();
2023-12-09 22:55:47 +00:00
let previous = self
.variables
.write()?
.insert(key, (value, value_type.clone()));
Ok(previous)
}
pub fn set_type(&self, key: String, r#type: Type) -> Result<Option<(Value, Type)>> {
log::info!("Setting type {key} = {}", r#type);
let previous = self.variables.write()?.insert(key, (Value::none(), r#type));
Ok(previous)
}
2024-01-28 18:30:57 +00:00
pub fn as_text_table(&self) -> Table {
let variables = self.variables.read().unwrap().clone().into_iter();
let mut table = Table::with_styles(Styles::default().with(HAlign::Centred));
for (key, (value, r#type)) in variables {
if let Value::Map(map) = value {
table.push_row(Row::new(
Styles::default(),
vec![key.into(), map.as_text_table().into(), "".into()],
));
} else if let Value::List(list) = value {
table.push_row(Row::new(
Styles::default(),
vec![
key.into(),
list.as_text_table().into(),
r#type.to_string().into(),
],
));
} else {
table.push_row([key, value.to_string(), r#type.to_string()]);
};
}
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-26 20:00:06 +00:00
impl Eq for Map {}
impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
left.eq(right)
}
}
impl Ord for Map {
fn cmp(&self, other: &Self) -> Ordering {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
left.cmp(right)
}
}
impl PartialOrd for Map {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2023-12-30 03:39:50 +00:00
Some(self.cmp(other))
2023-10-26 20:00:06 +00:00
}
}
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
}
}
2023-10-25 20:44:50 +00:00
impl Serialize for Map {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let variables = self.variables.read().unwrap();
let mut map = serializer.serialize_map(Some(variables.len()))?;
for (key, (value, _type)) in variables.iter() {
map.serialize_entry(key, value)?;
}
map.end()
2023-10-25 20:44:50 +00:00
}
}
struct MapVisitor {
marker: PhantomData<fn() -> Map>,
}
impl MapVisitor {
fn new() -> Self {
MapVisitor {
marker: PhantomData,
}
}
}
impl<'de> Visitor<'de> for MapVisitor {
type Value = Map;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("Any valid whale data.")
}
fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error>
where
M: MapAccess<'de>,
{
let map = Map::new();
{
while let Some((key, value)) = access.next_entry::<String, Value>()? {
2024-01-10 01:38:40 +00:00
map.set(key, value).unwrap();
}
}
Ok(map)
}
}
impl<'de> Deserialize<'de> for Map {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(MapVisitor::new())
}
}