1
0
dust/src/abstract_tree/index.rs

123 lines
4.1 KiB
Rust
Raw Normal View History

2023-10-29 23:31:06 +00:00
use serde::{Deserialize, Serialize};
2024-01-10 20:03:52 +00:00
use crate::{
AbstractTree, Error, Format, IndexExpression, List, Map, Result, SyntaxNode, Type, Value,
};
2023-10-29 23:31:06 +00:00
2023-12-06 19:13:22 +00:00
/// Abstract representation of an index expression.
///
/// An index is a means of accessing values stored in list, maps and strings.
2023-10-29 23:31:06 +00:00
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Index {
pub collection: IndexExpression,
pub index: IndexExpression,
pub index_end: Option<IndexExpression>,
2023-10-29 23:31:06 +00:00
}
impl AbstractTree for Index {
2024-01-10 20:03:52 +00:00
fn from_syntax(node: SyntaxNode, source: &str, context: &Map) -> Result<Self> {
2023-12-30 02:15:03 +00:00
Error::expect_syntax_node(source, "index", node)?;
2023-10-29 23:31:06 +00:00
let collection_node = node.child(0).unwrap();
2024-01-10 20:03:52 +00:00
let collection = IndexExpression::from_syntax(collection_node, source, context)?;
2023-10-29 23:31:06 +00:00
let index_node = node.child(2).unwrap();
2024-01-10 20:03:52 +00:00
let index = IndexExpression::from_syntax(index_node, source, context)?;
2023-10-29 23:31:06 +00:00
let index_end_node = node.child(4);
2023-10-29 23:31:06 +00:00
let index_end = if let Some(index_end_node) = index_end_node {
2024-01-10 20:03:52 +00:00
Some(IndexExpression::from_syntax(
2023-11-30 03:54:46 +00:00
index_end_node,
2024-01-10 20:03:52 +00:00
source,
2023-11-30 03:54:46 +00:00
context,
)?)
2023-10-29 23:31:06 +00:00
} else {
None
};
Ok(Index {
collection,
index,
index_end,
})
}
2023-11-30 00:23:42 +00:00
fn run(&self, source: &str, context: &Map) -> Result<Value> {
2023-11-15 01:00:57 +00:00
let collection = self.collection.run(source, context)?;
2023-10-29 23:31:06 +00:00
2023-11-15 01:00:57 +00:00
match collection {
2023-10-29 23:31:06 +00:00
Value::List(list) => {
let index = self.index.run(source, context)?.as_integer()? as usize;
let item = if let Some(index_end) = &self.index_end {
let index_end = index_end.run(source, context)?.as_integer()? as usize;
let sublist = list.items()[index..=index_end].to_vec();
Value::List(List::with_items(sublist))
} else {
list.items().get(index).cloned().unwrap_or_default()
};
Ok(item)
}
2023-11-15 01:41:57 +00:00
Value::Map(map) => {
2024-01-28 22:46:15 +00:00
let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index {
2023-11-10 21:24:19 +00:00
let key = identifier.inner();
2024-01-28 22:46:15 +00:00
let value = map
.variables()?
2023-12-09 22:15:41 +00:00
.get(key)
.map(|(value, _)| value.clone())
2024-01-28 22:46:15 +00:00
.unwrap_or_default();
2023-11-10 21:24:19 +00:00
2024-01-28 22:46:15 +00:00
(key.clone(), value)
} else {
let index_value = self.index.run(source, context)?;
let key = index_value.as_string()?;
let value = map
.variables()?
.get(key.as_str())
2023-12-09 22:15:41 +00:00
.map(|(value, _)| value.clone())
2024-01-28 22:46:15 +00:00
.unwrap_or_default();
(key.clone(), value)
2023-11-10 21:24:19 +00:00
};
2023-10-29 23:31:06 +00:00
2024-01-28 22:46:15 +00:00
if value.is_none() {
Err(Error::VariableIdentifierNotFound(key))
} else {
Ok(value)
}
2023-10-29 23:31:06 +00:00
}
Value::String(string) => {
let index = self.index.run(source, context)?.as_integer()? as usize;
let item = string.chars().nth(index).unwrap_or_default();
2023-10-29 23:31:06 +00:00
Ok(Value::string(item.to_string()))
2023-10-29 23:31:06 +00:00
}
2023-11-15 01:00:57 +00:00
_ => Err(Error::ExpectedCollection { actual: collection }),
2023-10-29 23:31:06 +00:00
}
}
2023-11-30 00:23:42 +00:00
2023-12-05 22:08:22 +00:00
fn expected_type(&self, context: &Map) -> Result<Type> {
match self.collection.expected_type(context)? {
Type::List(item_type) => Ok(*item_type.clone()),
2024-01-06 08:47:54 +00:00
Type::Map(_) => Ok(Type::Any),
2023-12-26 22:19:12 +00:00
Type::None => Ok(Type::None),
2024-01-01 02:46:45 +00:00
r#type => Ok(r#type),
}
2023-11-30 00:23:42 +00:00
}
2023-10-29 23:31:06 +00:00
}
2024-01-06 10:00:36 +00:00
2024-01-06 13:11:09 +00:00
impl Format for Index {
fn format(&self, output: &mut String, indent_level: u8) {
self.collection.format(output, indent_level);
output.push(':');
self.index.format(output, indent_level);
2024-01-06 10:00:36 +00:00
2024-01-06 13:11:09 +00:00
if let Some(expression) = &self.index_end {
output.push_str("..");
expression.format(output, indent_level);
2024-01-06 10:00:36 +00:00
}
}
}