1
0
dust/src/value/table.rs

351 lines
9.2 KiB
Rust
Raw Normal View History

2023-10-26 22:03:59 +00:00
use crate::{Error, List, Map, Result, Value};
2023-08-22 15:40:50 +00:00
use comfy_table::{Cell, Color, ContentArrangement, Table as ComfyTable};
use serde::{Deserialize, Serialize};
use std::{
cmp::Ordering,
fmt::{self, Display, Formatter},
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Table {
2023-10-03 03:19:01 +00:00
headers: Vec<String>,
2023-08-22 15:40:50 +00:00
rows: Vec<Vec<Value>>,
primary_key_index: usize,
}
impl Table {
2023-10-03 03:19:01 +00:00
pub fn new(headers: Vec<String>) -> Self {
2023-08-22 15:40:50 +00:00
Table {
2023-10-03 03:19:01 +00:00
headers,
2023-08-22 15:40:50 +00:00
rows: Vec::new(),
primary_key_index: 0,
}
}
2023-10-03 03:19:01 +00:00
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,
}
}
2023-08-22 15:40:50 +00:00
pub fn reserve(&mut self, additional: usize) {
self.rows.reserve(additional);
}
2023-10-22 17:07:40 +00:00
pub fn headers(&self) -> &Vec<String> {
2023-10-03 03:19:01 +00:00
&self.headers
2023-08-22 15:40:50 +00:00
}
pub fn rows(&self) -> &Vec<Vec<Value>> {
&self.rows
}
pub fn len(&self) -> usize {
self.rows.len()
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
pub fn sort(&mut self) {
self.rows.sort();
}
pub fn insert(&mut self, row: Vec<Value>) -> Result<()> {
2023-10-03 03:19:01 +00:00
if row.len() != self.headers.len() {
2023-08-22 15:40:50 +00:00
return Err(Error::WrongColumnAmount {
2023-10-03 03:19:01 +00:00
expected: self.headers.len(),
2023-08-22 15:40:50 +00:00
actual: row.len(),
});
}
self.rows.push(row);
Ok(())
}
pub fn remove(&mut self, index: usize) -> Result<()> {
self.rows.remove(index);
Ok(())
}
pub fn get_row(&self, index: usize) -> Option<&Vec<Value>> {
self.rows.get(index)
}
pub fn get(&self, value: &Value) -> Option<&Vec<Value>> {
2023-10-22 17:07:40 +00:00
let primary_key = self.headers().get(self.primary_key_index)?;
2023-08-22 15:40:50 +00:00
self.get_where(primary_key, value)
}
pub fn get_where(&self, column_name: &str, expected: &Value) -> Option<&Vec<Value>> {
let column_index = self.get_column_index(column_name)?;
for row in &self.rows {
if let Some(actual) = row.get(column_index) {
if actual == expected {
return Some(row);
}
}
}
None
}
pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> {
2023-10-03 03:19:01 +00:00
let mut filtered = Table::new(self.headers.clone());
2023-08-22 15:40:50 +00:00
let column_index = self.get_column_index(column_name)?;
for row in &self.rows {
let actual = row.get(column_index).unwrap();
if actual == expected {
let _ = filtered.insert(row.clone());
}
}
Some(filtered)
}
pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
2023-10-03 03:19:01 +00:00
let column_names = &self.headers;
2023-08-22 15:40:50 +00:00
for (i, column) in column_names.iter().enumerate() {
if column == column_name {
return Some(i);
}
}
None
}
}
impl Display for Table {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut table = ComfyTable::new();
table
.load_preset("││──├─┼┤│ ┬┴╭╮╰╯")
.set_content_arrangement(ContentArrangement::Dynamic)
2023-10-03 03:19:01 +00:00
.set_header(&self.headers);
2023-08-22 15:40:50 +00:00
for row in &self.rows {
let row = row.iter().map(|value| {
let text = match value {
2023-08-29 00:03:13 +00:00
Value::List(list) => {
let mut string = "(".to_string();
2023-10-26 22:03:59 +00:00
for (index, value) in list.items().iter().enumerate() {
2023-08-29 00:03:13 +00:00
if index > 0 {
string.push_str(", ");
}
string.push_str(&value.to_string());
}
2023-10-30 19:48:43 +00:00
string.push(')');
2023-08-29 00:03:13 +00:00
string
}
2023-08-22 15:40:50 +00:00
Value::Map(map) => format!("Map ({} items)", map.len()),
Value::Table(table) => format!("Table ({} items)", table.len()),
Value::Function(_) => "Function".to_string(),
2023-10-05 12:03:14 +00:00
Value::Empty => "Empty".to_string(),
2023-08-22 15:40:50 +00:00
value => value.to_string(),
};
let mut cell = Cell::new(text).bg(Color::Rgb {
r: 40,
g: 40,
b: 40,
});
if value.is_string() {
cell = cell.fg(Color::Green);
}
if value.is_integer() {
cell = cell.fg(Color::Blue);
}
if value.is_boolean() {
cell = cell.fg(Color::Red);
}
if value.is_function() {
cell = cell.fg(Color::Cyan);
}
cell
});
table.add_row(row);
}
2023-10-03 03:19:01 +00:00
if self.headers.is_empty() {
2023-08-22 15:40:50 +00:00
table.set_header(["empty"]);
}
write!(f, "{table}")
}
}
impl From<&Value> for Table {
fn from(value: &Value) -> Self {
match value {
2023-10-05 12:03:14 +00:00
Value::String(string) => {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["string".to_string()]);
table
2023-10-05 12:03:14 +00:00
.insert(vec![Value::String(string.to_string())])
2023-08-22 15:40:50 +00:00
.unwrap();
table
}
2023-10-05 12:03:14 +00:00
Value::Float(float) => {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["float".to_string()]);
2023-10-05 12:03:14 +00:00
table.insert(vec![Value::Float(*float)]).unwrap();
2023-08-22 15:40:50 +00:00
table
}
2023-10-05 12:03:14 +00:00
Value::Integer(integer) => {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["integer".to_string()]);
2023-10-05 12:03:14 +00:00
table.insert(vec![Value::Integer(*integer)]).unwrap();
2023-08-22 15:40:50 +00:00
table
}
2023-10-05 12:03:14 +00:00
Value::Boolean(boolean) => {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["boolean".to_string()]);
2023-10-05 12:03:14 +00:00
table.insert(vec![Value::Boolean(*boolean)]).unwrap();
2023-08-22 15:40:50 +00:00
table
}
Value::List(list) => Self::from(list),
2023-10-05 12:03:14 +00:00
Value::Empty => Table::new(Vec::with_capacity(0)),
2023-08-22 15:40:50 +00:00
Value::Map(map) => Self::from(map),
Value::Table(table) => table.clone(),
Value::Function(function) => {
let mut table = Table::new(vec!["function".to_string()]);
table
.insert(vec![Value::Function(function.clone())])
.unwrap();
table
}
}
}
}
2023-10-26 22:03:59 +00:00
impl From<&List> for Table {
fn from(list: &List) -> Self {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["index".to_string(), "item".to_string()]);
2023-10-26 22:03:59 +00:00
for (i, value) in list.items().iter().enumerate() {
2023-08-22 15:40:50 +00:00
table
2023-10-05 12:03:14 +00:00
.insert(vec![Value::Integer(i as i64), value.clone()])
2023-08-22 15:40:50 +00:00
.unwrap();
}
table
}
}
2023-10-26 22:03:59 +00:00
impl From<&mut List> for Table {
fn from(list: &mut List) -> Self {
2023-08-22 15:40:50 +00:00
let mut table = Table::new(vec!["index".to_string(), "item".to_string()]);
2023-10-26 22:03:59 +00:00
for (i, value) in list.items().iter().enumerate() {
2023-08-22 15:40:50 +00:00
if let Ok(list) = value.as_list() {
2023-10-26 22:03:59 +00:00
table.insert(list.items().clone()).unwrap();
2023-08-22 15:40:50 +00:00
} else {
table
2023-10-05 12:03:14 +00:00
.insert(vec![Value::Integer(i as i64), value.clone()])
2023-08-22 15:40:50 +00:00
.unwrap();
}
}
table
}
}
2023-10-25 20:44:50 +00:00
impl From<Map> for Table {
fn from(map: Map) -> Self {
let variables = map.variables();
let keys = variables.keys().cloned().collect();
let values = variables.values().cloned().collect();
2023-08-22 15:40:50 +00:00
let mut table = Table::new(keys);
table
.insert(values)
.expect("Failed to create Table from Map. This is a no-op.");
table
}
}
2023-10-25 20:44:50 +00:00
impl From<&Map> for Table {
fn from(map: &Map) -> Self {
let variables = map.variables();
let keys = variables.keys().cloned().collect();
let values = variables.values().cloned().collect();
2023-08-22 15:40:50 +00:00
let mut table = Table::new(keys);
table
.insert(values)
.expect("Failed to create Table from Map. This is a no-op.");
table
}
}
2023-10-25 20:44:50 +00:00
impl From<&mut Map> for Table {
fn from(map: &mut Map) -> Self {
let variables = map.variables();
let keys = variables.keys().cloned().collect();
let values = variables.values().cloned().collect();
2023-08-22 15:40:50 +00:00
let mut table = Table::new(keys);
table
.insert(values)
.expect("Failed to create Table from Map. This is a no-op.");
table
}
}
impl Eq for Table {}
impl PartialEq for Table {
fn eq(&self, other: &Self) -> bool {
2023-10-03 03:19:01 +00:00
if self.headers != other.headers {
2023-08-22 15:40:50 +00:00
return false;
}
self.rows == other.rows
}
}
impl PartialOrd for Table {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2023-10-03 03:19:01 +00:00
self.headers.partial_cmp(&other.headers)
2023-08-22 15:40:50 +00:00
}
}
impl Ord for Table {
fn cmp(&self, other: &Self) -> Ordering {
2023-10-03 03:19:01 +00:00
self.headers.cmp(&other.headers)
2023-08-22 15:40:50 +00:00
}
}