Implement tables
This commit is contained in:
parent
a42b43ed78
commit
5551f40ffd
133
src/interface.rs
133
src/interface.rs
@ -5,7 +5,7 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::{Parser, Tree as TSTree, TreeCursor};
|
||||
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
||||
|
||||
use crate::{language, Error, Primitive, Result, Value, VariableMap};
|
||||
|
||||
@ -63,7 +63,7 @@ pub trait EvaluatorTree: Sized {
|
||||
///
|
||||
/// If necessary, the source code can be accessed directly by getting the
|
||||
/// node's byte range.
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self>;
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self>;
|
||||
|
||||
/// Execute dust code by traversing the tree
|
||||
fn run(&self, context: &mut VariableMap) -> Result<Value>;
|
||||
@ -109,10 +109,8 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
||||
|
||||
assert_eq!(cursor_0.node().kind(), "root");
|
||||
|
||||
cursor_1.goto_first_child();
|
||||
|
||||
for _ in node.children(&mut cursor_0) {
|
||||
let item_result = Item::new(self.source, &mut cursor_1);
|
||||
for item_node in node.children(&mut cursor_0) {
|
||||
let item_result = Item::from_syntax_node(item_node, self.source);
|
||||
|
||||
match item_result {
|
||||
Ok(item) => {
|
||||
@ -140,12 +138,10 @@ pub enum Item {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Item {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
cursor.goto_first_child();
|
||||
let child = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
debug_assert_eq!(node.kind(), "item");
|
||||
|
||||
assert_eq!(node.kind(), "item");
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
if child.kind() == "comment" {
|
||||
let byte_range = child.byte_range();
|
||||
@ -153,7 +149,7 @@ impl EvaluatorTree for Item {
|
||||
|
||||
Ok(Item::Comment(comment_text.to_string()))
|
||||
} else if child.kind() == "statement" {
|
||||
Ok(Item::Statement(Statement::new(source, cursor)?))
|
||||
Ok(Item::Statement(Statement::from_syntax_node(child, source)?))
|
||||
} else {
|
||||
Err(Error::UnexpectedSyntax {
|
||||
expected: "comment or statement",
|
||||
@ -182,12 +178,15 @@ pub enum Statement {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Statement {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
cursor.goto_first_child();
|
||||
let child = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
debug_assert_eq!(node.kind(), "statement");
|
||||
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
match child.kind() {
|
||||
"expression" => Ok(Self::Expression(Expression::new(source, cursor)?)),
|
||||
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
||||
child, source,
|
||||
)?)),
|
||||
_ => Err(Error::UnexpectedSyntax {
|
||||
expected: "expression",
|
||||
actual: child.kind(),
|
||||
@ -214,20 +213,24 @@ pub enum Expression {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Expression {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
cursor.goto_first_child();
|
||||
let child = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
debug_assert_eq!(node.kind(), "expression");
|
||||
|
||||
assert_eq!(node.kind(), "expression");
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
let expression = match child.kind() {
|
||||
"identifier" => Self::Identifier(Identifier::new(source, cursor)?),
|
||||
"value" => Expression::Value(Value::from_source(source, cursor)?),
|
||||
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)),
|
||||
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)),
|
||||
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)),
|
||||
"function_call" => Expression::FunctionCall(FunctionCall::new(source, cursor)?),
|
||||
"identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?),
|
||||
"value" => Expression::Value(Value::from_syntax_node(child, source)?),
|
||||
"control_flow" => {
|
||||
Expression::ControlFlow(Box::new(ControlFlow::from_syntax_node(child, source)?))
|
||||
}
|
||||
"assignment" => {
|
||||
Expression::Assignment(Box::new(Assignment::from_syntax_node(child, source)?))
|
||||
}
|
||||
"math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)),
|
||||
"function_call" => {
|
||||
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
|
||||
}
|
||||
_ => return Err(Error::UnexpectedSyntax {
|
||||
expected:
|
||||
"identifier, operation, control_flow, assignment, math, function_call or value",
|
||||
@ -265,9 +268,7 @@ impl Identifier {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Identifier {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
assert_eq!(node.kind(), "identifier");
|
||||
|
||||
let identifier = &source[node.byte_range()];
|
||||
@ -290,35 +291,26 @@ pub struct ControlFlow {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for ControlFlow {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
assert_eq!(node.kind(), "control_flow");
|
||||
|
||||
println!("{node:?}");
|
||||
|
||||
// Skip the child nodes for the keywords "if", "then" and "else".
|
||||
|
||||
let if_node = node.child_by_field_name("if_expression").unwrap();
|
||||
|
||||
cursor.reset(if_node);
|
||||
|
||||
let if_expression = Expression::new(source, cursor)?;
|
||||
|
||||
println!("{:?}", cursor.node());
|
||||
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
||||
|
||||
let then_node = node.child_by_field_name("then_statement").unwrap();
|
||||
let then_statement = Statement::from_syntax_node(then_node, source)?;
|
||||
|
||||
cursor.reset(then_node);
|
||||
|
||||
let position = cursor.node();
|
||||
let then_statement = Statement::new(source, cursor)?;
|
||||
|
||||
cursor.reset(position);
|
||||
let else_node = node.child_by_field_name("else_statement");
|
||||
let else_statement = if let Some(node) = else_node {
|
||||
Some(Statement::from_syntax_node(node, source)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(ControlFlow {
|
||||
if_expression,
|
||||
then_statement,
|
||||
else_statement: None,
|
||||
else_statement,
|
||||
})
|
||||
}
|
||||
|
||||
@ -342,18 +334,14 @@ pub struct Assignment {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Assignment {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
cursor.goto_first_child();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
assert_eq!(node.kind(), "assignment");
|
||||
|
||||
cursor.goto_next_sibling();
|
||||
let identifier = Identifier::new(source, cursor)?;
|
||||
let identifier_node = node.child(0).unwrap();
|
||||
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||
|
||||
cursor.goto_next_sibling();
|
||||
let statement = Statement::new(source, cursor)?;
|
||||
|
||||
cursor.goto_next_sibling();
|
||||
let statement_node = node.child(2).unwrap();
|
||||
let statement = Statement::from_syntax_node(statement_node, source)?;
|
||||
|
||||
Ok(Assignment {
|
||||
identifier,
|
||||
@ -379,15 +367,13 @@ pub struct Math {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for Math {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
assert_eq!(node.kind(), "math");
|
||||
|
||||
cursor.goto_first_child();
|
||||
let left = Expression::new(source, cursor)?;
|
||||
let left_node = node.child(0).unwrap();
|
||||
let left = Expression::from_syntax_node(left_node, source)?;
|
||||
|
||||
cursor.goto_next_sibling();
|
||||
let operator_node = cursor.node();
|
||||
let operator_node = left_node.next_sibling().unwrap();
|
||||
let operator = match operator_node.kind() {
|
||||
"+" => MathOperator::Add,
|
||||
"-" => MathOperator::Subtract,
|
||||
@ -403,8 +389,8 @@ impl EvaluatorTree for Math {
|
||||
}
|
||||
};
|
||||
|
||||
cursor.goto_next_sibling();
|
||||
let right = Expression::new(source, cursor)?;
|
||||
let right_node = operator_node.next_sibling().unwrap();
|
||||
let right = Expression::from_syntax_node(right_node, source)?;
|
||||
|
||||
Ok(Math {
|
||||
left,
|
||||
@ -444,22 +430,15 @@ pub struct FunctionCall {
|
||||
}
|
||||
|
||||
impl EvaluatorTree for FunctionCall {
|
||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
assert_eq!(node.kind(), "function_call");
|
||||
|
||||
cursor.goto_first_child();
|
||||
let identifier = Identifier::new(source, cursor)?;
|
||||
let identifier_node = node.child(0).unwrap();
|
||||
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||
|
||||
let mut expressions = Vec::new();
|
||||
|
||||
for index in 2..node.child_count() - 1 {
|
||||
cursor.goto_next_sibling();
|
||||
|
||||
let expression = Expression::new(source, cursor)?;
|
||||
|
||||
expressions.push(expression);
|
||||
}
|
||||
todo!();
|
||||
|
||||
Ok(FunctionCall {
|
||||
identifier,
|
||||
|
224
src/value/mod.rs
224
src/value/mod.rs
@ -37,6 +37,50 @@ pub enum Primitive {
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
match node.kind() {
|
||||
"integer" => Primitive::integer_from_source(source, node.byte_range()),
|
||||
"float" => Primitive::float_from_source(source, node.byte_range()),
|
||||
"boolean" => Primitive::boolean_from_source(source, node.byte_range()),
|
||||
"string" => Primitive::string_from_source(source, node.byte_range()),
|
||||
"empty" => Ok(Primitive::Empty),
|
||||
_ => Err(Error::UnexpectedSyntax {
|
||||
expected: "integer, float, boolean, string or empty",
|
||||
actual: node.kind(),
|
||||
location: node.start_position(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||
|
||||
Ok(Primitive::Integer(raw))
|
||||
}
|
||||
|
||||
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||
|
||||
Ok(Primitive::Float(raw))
|
||||
}
|
||||
|
||||
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||
|
||||
Ok(Primitive::Boolean(raw))
|
||||
}
|
||||
|
||||
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||
|
||||
Ok(Primitive::String(without_quotes.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Primitive {}
|
||||
|
||||
impl Ord for Primitive {
|
||||
@ -74,53 +118,90 @@ pub enum Value {
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn from_source(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
cursor.goto_first_child();
|
||||
let child = cursor.node();
|
||||
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
debug_assert_eq!(node.kind(), "value");
|
||||
|
||||
assert_eq!(node.kind(), "value");
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
match child.kind() {
|
||||
"integer" | "float" | "boolean" | "string" | "empty" => {
|
||||
Value::simple_from_syntax_node(node, source)
|
||||
}
|
||||
"integer" | "float" | "boolean" | "string" | "empty" => Ok(Value::Primitive(
|
||||
Primitive::from_syntax_node(child, source)?,
|
||||
)),
|
||||
"list" => {
|
||||
let list_length = child.named_child_count();
|
||||
let mut values = Vec::with_capacity(list_length);
|
||||
let item_count = child.named_child_count();
|
||||
let mut values = Vec::with_capacity(item_count);
|
||||
let mut current_node = child.child(1).unwrap();
|
||||
|
||||
cursor.goto_first_child();
|
||||
while values.len() < item_count {
|
||||
if current_node.is_named() {
|
||||
let value = Value::from_syntax_node(current_node, source)?;
|
||||
|
||||
for value_node in child.children_by_field_name("item", &mut cursor) {
|
||||
let value = Value::simple_from_syntax_node(value_node, source)?;
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
values.push(value);
|
||||
current_node = current_node.next_sibling().unwrap();
|
||||
}
|
||||
|
||||
Ok(Value::List(values))
|
||||
}
|
||||
"table" => {
|
||||
let mut column_names = Vec::new();
|
||||
let mut current_node = child.child(0).unwrap();
|
||||
let header_and_row_count = child.named_child_count();
|
||||
|
||||
let mut table = Table::new(column_names);
|
||||
let mut headers = Vec::new();
|
||||
let mut rows = Vec::new();
|
||||
|
||||
while headers.len() + rows.len() < header_and_row_count {
|
||||
println!("{current_node:?}");
|
||||
|
||||
if current_node.kind() == "identifier" {
|
||||
let identifier = Identifier::from_syntax_node(current_node, source)?;
|
||||
let identifier_text = identifier.take_inner();
|
||||
|
||||
headers.push(identifier_text);
|
||||
}
|
||||
|
||||
if current_node.kind() == "list" {
|
||||
let value = Value::list_from_syntax_node(current_node, source)?;
|
||||
let row = value.into_inner_list()?;
|
||||
|
||||
rows.push(row);
|
||||
}
|
||||
|
||||
if let Some(node) = current_node.next_sibling() {
|
||||
current_node = node;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let table = Table::from_raw_parts(headers, rows);
|
||||
|
||||
Ok(Value::Table(table))
|
||||
}
|
||||
"map" => {
|
||||
let mut map = VariableMap::new();
|
||||
|
||||
let pair_count = child.named_child_count();
|
||||
let mut current_key = String::new();
|
||||
let mut current_node = child.child(0).unwrap();
|
||||
|
||||
for key_value_node in child.children_by_field_name("key_value_pair", &mut cursor) {
|
||||
if key_value_node.kind() == "identifier" {
|
||||
let identifier_text = &source[key_value_node.byte_range()];
|
||||
while map.len() < pair_count {
|
||||
if current_node.kind() == "identifier" {
|
||||
let identifier_text = &source[current_node.byte_range()];
|
||||
current_key = identifier_text.to_string();
|
||||
}
|
||||
|
||||
if key_value_node.kind() == "value" {
|
||||
let value = Value::simple_from_syntax_node(key_value_node, source)?;
|
||||
if current_node.kind() == "value" {
|
||||
let value = Value::from_syntax_node(current_node, source)?;
|
||||
|
||||
map.set_value(current_key.to_string(), value)?;
|
||||
}
|
||||
|
||||
if let Some(node) = current_node.next_sibling() {
|
||||
current_node = node;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Map(map))
|
||||
@ -133,17 +214,17 @@ impl Value {
|
||||
for index in 0..child_count {
|
||||
let child = child.child(index).unwrap();
|
||||
|
||||
if child.kind() == "identifier" {
|
||||
let identifier = Identifier::new(source, cursor)?;
|
||||
// if child.kind() == "identifier" {
|
||||
// let identifier = Identifier::new(source, cursor)?;
|
||||
|
||||
identifiers.push(identifier)
|
||||
}
|
||||
// identifiers.push(identifier)
|
||||
// }
|
||||
|
||||
if child.kind() == "statement" {
|
||||
let statement = Statement::new(source, cursor)?;
|
||||
// if child.kind() == "statement" {
|
||||
// let statement = Statement::new(source, cursor)?;
|
||||
|
||||
statements.push(statement)
|
||||
}
|
||||
// statements.push(statement)
|
||||
// }
|
||||
}
|
||||
|
||||
Ok(Value::Function(Function::new(identifiers, statements)))
|
||||
@ -156,56 +237,53 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a simple value from the given source code and a node in the
|
||||
/// syntax tree.
|
||||
///
|
||||
///
|
||||
pub fn simple_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
let child = node.child(0).unwrap();
|
||||
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||
debug_assert_eq!(node.kind(), "list");
|
||||
|
||||
match child.kind() {
|
||||
"integer" => Value::integer_from_source(source, child.byte_range()),
|
||||
"float" => Value::float_from_source(source, child.byte_range()),
|
||||
"boolean" => Value::boolean_from_source(source, child.byte_range()),
|
||||
"string" => Value::string_from_source(source, child.byte_range()),
|
||||
"empty" => Ok(Value::Primitive(Primitive::Empty)),
|
||||
_ => Err(Error::UnexpectedSyntax {
|
||||
expected: "integer, float, boolean, string or empty",
|
||||
actual: child.kind(),
|
||||
location: child.start_position(),
|
||||
}),
|
||||
let item_count = node.named_child_count();
|
||||
let mut values = Vec::with_capacity(item_count);
|
||||
let mut current_node = node.child(1).unwrap();
|
||||
|
||||
while values.len() < item_count {
|
||||
if current_node.is_named() {
|
||||
let value = Value::from_syntax_node(current_node, source)?;
|
||||
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
current_node = current_node.next_sibling().unwrap();
|
||||
}
|
||||
|
||||
Ok(Value::List(values))
|
||||
}
|
||||
|
||||
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||
// pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
// let value_snippet = &source[byte_range];
|
||||
// let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||
|
||||
Ok(Value::Primitive(Primitive::Integer(raw)))
|
||||
}
|
||||
// Ok(Primitive::Integer(raw))
|
||||
// }
|
||||
|
||||
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||
// pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
// let value_snippet = &source[byte_range];
|
||||
// let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||
|
||||
Ok(Value::Primitive(Primitive::Float(raw)))
|
||||
}
|
||||
// Ok(Primitive::Float(raw))
|
||||
// }
|
||||
|
||||
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||
// pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
// let value_snippet = &source[byte_range];
|
||||
// let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||
|
||||
Ok(Value::Primitive(Primitive::Boolean(raw)))
|
||||
}
|
||||
// Ok(Primitive::Boolean(raw))
|
||||
// }
|
||||
|
||||
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
let value_snippet = &source[byte_range];
|
||||
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||
// pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||
// let value_snippet = &source[byte_range];
|
||||
// let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||
|
||||
Ok(Value::Primitive(Primitive::String(
|
||||
without_quotes.to_string(),
|
||||
)))
|
||||
}
|
||||
// Ok(Primitive::String(without_quotes.to_string()))
|
||||
// }
|
||||
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
ValueType::from(self)
|
||||
@ -532,7 +610,13 @@ impl Display for Value {
|
||||
Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int),
|
||||
Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean),
|
||||
Value::Primitive(Primitive::Empty) => write!(f, "()"),
|
||||
Value::List(list) => Table::from(list).fmt(f),
|
||||
Value::List(list) => {
|
||||
write!(f, "(")?;
|
||||
for value in list {
|
||||
write!(f, " {value} ")?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Value::Map(map) => write!(f, "{map}"),
|
||||
Value::Table(table) => write!(f, "{table}"),
|
||||
Value::Function(function) => write!(f, "{function}"),
|
||||
|
@ -8,26 +8,42 @@ use std::{
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Table {
|
||||
header: Vec<String>,
|
||||
headers: Vec<String>,
|
||||
rows: Vec<Vec<Value>>,
|
||||
primary_key_index: usize,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new(column_names: Vec<String>) -> Self {
|
||||
pub fn new(headers: Vec<String>) -> Self {
|
||||
Table {
|
||||
header: column_names,
|
||||
headers,
|
||||
rows: Vec::new(),
|
||||
primary_key_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize, headers: Vec<String>) -> Self {
|
||||
Table {
|
||||
headers,
|
||||
rows: Vec::with_capacity(capacity),
|
||||
primary_key_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_raw_parts(headers: Vec<String>, rows: Vec<Vec<Value>>) -> Self {
|
||||
Table {
|
||||
headers,
|
||||
rows,
|
||||
primary_key_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
self.rows.reserve(additional);
|
||||
}
|
||||
|
||||
pub fn column_names(&self) -> &Vec<String> {
|
||||
&self.header
|
||||
&self.headers
|
||||
}
|
||||
|
||||
pub fn rows(&self) -> &Vec<Vec<Value>> {
|
||||
@ -47,9 +63,9 @@ impl Table {
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, row: Vec<Value>) -> Result<()> {
|
||||
if row.len() != self.header.len() {
|
||||
if row.len() != self.headers.len() {
|
||||
return Err(Error::WrongColumnAmount {
|
||||
expected: self.header.len(),
|
||||
expected: self.headers.len(),
|
||||
actual: row.len(),
|
||||
});
|
||||
}
|
||||
@ -82,10 +98,10 @@ impl Table {
|
||||
let mut new_row = Vec::new();
|
||||
|
||||
for (i, value) in row.iter().enumerate() {
|
||||
let column_name = self.header.get(i).unwrap();
|
||||
let column_name = self.headers.get(i).unwrap();
|
||||
let new_table_column_index =
|
||||
new_table
|
||||
.header
|
||||
.headers
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(index, new_column_name)| {
|
||||
@ -125,7 +141,7 @@ impl Table {
|
||||
}
|
||||
|
||||
pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> {
|
||||
let mut filtered = Table::new(self.header.clone());
|
||||
let mut filtered = Table::new(self.headers.clone());
|
||||
let column_index = self.get_column_index(column_name)?;
|
||||
|
||||
for row in &self.rows {
|
||||
@ -140,7 +156,7 @@ impl Table {
|
||||
}
|
||||
|
||||
pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
|
||||
let column_names = &self.header;
|
||||
let column_names = &self.headers;
|
||||
for (i, column) in column_names.iter().enumerate() {
|
||||
if column == column_name {
|
||||
return Some(i);
|
||||
@ -157,7 +173,7 @@ impl Display for Table {
|
||||
table
|
||||
.load_preset("││──├─┼┤│ ┬┴╭╮╰╯")
|
||||
.set_content_arrangement(ContentArrangement::Dynamic)
|
||||
.set_header(&self.header);
|
||||
.set_header(&self.headers);
|
||||
|
||||
for row in &self.rows {
|
||||
let row = row.iter().map(|value| {
|
||||
@ -209,7 +225,7 @@ impl Display for Table {
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
if self.header.is_empty() {
|
||||
if self.headers.is_empty() {
|
||||
table.set_header(["empty"]);
|
||||
}
|
||||
|
||||
@ -360,7 +376,7 @@ impl Eq for Table {}
|
||||
|
||||
impl PartialEq for Table {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.header != other.header {
|
||||
if self.headers != other.headers {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -370,12 +386,12 @@ impl PartialEq for Table {
|
||||
|
||||
impl PartialOrd for Table {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.header.partial_cmp(&other.header)
|
||||
self.headers.partial_cmp(&other.headers)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Table {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.header.cmp(&other.header)
|
||||
self.headers.cmp(&other.headers)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user