use crate::dbs::Options; use crate::dbs::Runtime; use crate::dbs::Transaction; use crate::err::Error; use crate::sql::comment::mightbespace; use crate::sql::common::commas; use crate::sql::error::IResult; use crate::sql::number::Number; use crate::sql::operation::Operation; use crate::sql::strand::Strand; use crate::sql::value::{value, Value}; use nom::character::complete::char; use nom::combinator::opt; use nom::multi::separated_list0; use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; use std::fmt; use std::ops; #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)] pub struct Array { pub value: Vec, } impl From for Array { fn from(v: Value) -> Self { Array { value: vec![v], } } } impl From> for Array { fn from(v: Vec) -> Self { Array { value: v, } } } impl From> for Array { fn from(v: Vec) -> Self { Array { value: v.into_iter().map(|x| x.into()).collect(), } } } impl From> for Array { fn from(v: Vec) -> Self { Array { value: v.into_iter().map(|x| x.into()).collect(), } } } impl From>> for Array { fn from(v: Vec>) -> Self { Array { value: v.into_iter().map(|x| x.into()).collect(), } } } impl<'a> From> for Array { fn from(v: Vec<&str>) -> Self { Array { value: v.into_iter().map(Value::from).collect(), } } } impl From> for Array { fn from(v: Vec) -> Self { Array { value: v.into_iter().map(Value::from).collect(), } } } impl Array { pub fn new() -> Self { Array { value: Vec::default(), } } pub fn with_capacity(len: usize) -> Self { Array { value: Vec::with_capacity(len), } } pub fn len(&self) -> usize { self.value.len() } pub fn is_empty(&self) -> bool { self.value.is_empty() } pub fn as_ints(self) -> Vec { self.value.into_iter().map(|v| v.as_int()).collect() } pub fn as_floats(self) -> Vec { self.value.into_iter().map(|v| v.as_float()).collect() } pub fn as_numbers(self) -> Vec { self.value.into_iter().map(|v| v.as_number()).collect() } pub fn as_strands(self) -> Vec { self.value.into_iter().map(|v| v.as_strand()).collect() } pub fn as_point(mut self) -> [f64; 2] { match self.len() { 0 => [0.0, 0.0], 1 => [self.value.remove(0).as_float(), 0.0], _ => [self.value.remove(0).as_float(), self.value.remove(0).as_float()], } } pub fn to_operations(&self) -> Result, Error> { self.value .iter() .map(|v| match v { Value::Object(v) => v.to_operation(), _ => Err(Error::InvalidPatch { message: String::from("Operation must be an object"), }), }) .collect::, Error>>() } } impl Array { pub async fn compute( &self, ctx: &Runtime, opt: &Options, txn: &Transaction, doc: Option<&Value>, ) -> Result { let mut x = Vec::new(); for v in &self.value { match v.compute(ctx, opt, txn, doc).await { Ok(v) => x.push(v), Err(e) => return Err(e), }; } Ok(Value::Array(Array { value: x, })) } } impl fmt::Display for Array { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "[{}]", self.value.iter().map(|ref v| format!("{}", v)).collect::>().join(", ") ) } } impl Serialize for Array { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { if serializer.is_human_readable() { serializer.serialize_some(&self.value) } else { let mut val = serializer.serialize_struct("Array", 1)?; val.serialize_field("value", &self.value)?; val.end() } } } // ------------------------------ impl ops::Add for Array { type Output = Self; fn add(mut self, other: Value) -> Self { if !self.value.iter().any(|x| *x == other) { self.value.push(other) } self } } impl ops::Add for Array { type Output = Self; fn add(mut self, other: Self) -> Self { for v in other.value { if !self.value.iter().any(|x| *x == v) { self.value.push(v) } } self } } // ------------------------------ impl ops::Sub for Array { type Output = Self; fn sub(mut self, other: Value) -> Self { if let Some(p) = self.value.iter().position(|x| *x == other) { self.value.remove(p); } self } } impl ops::Sub for Array { type Output = Self; fn sub(mut self, other: Self) -> Self { for v in other.value { if let Some(p) = self.value.iter().position(|x| *x == v) { self.value.remove(p); } } self } } // ------------------------------ pub trait Abolish { fn abolish(&mut self, f: F) where F: FnMut(usize) -> bool; } impl Abolish for Vec { fn abolish(&mut self, mut f: F) where F: FnMut(usize) -> bool, { let len = self.len(); let mut del = 0; { let v = &mut **self; for i in 0..len { if f(i) { del += 1; } else if del > 0 { v.swap(i - del, i); } } } if del > 0 { self.truncate(len - del); } } } // ------------------------------ pub trait Combine { fn combine(self, other: Vec) -> Vec>; } impl Combine for Vec { fn combine(self, other: Vec) -> Vec> { let mut out = Vec::new(); for a in self.iter() { for b in other.iter() { out.push(vec![a.clone(), b.clone()]); } } out } } // ------------------------------ pub trait Concat { fn concat(self, other: Vec) -> Vec; } impl Concat for Vec { fn concat(mut self, mut other: Vec) -> Vec { self.append(&mut other); self } } // ------------------------------ pub trait Difference { fn difference(self, other: Vec) -> Vec; } impl Difference for Vec { fn difference(self, other: Vec) -> Vec { let mut out = Vec::new(); let mut other: Vec<_> = other.into_iter().collect(); for a in self.into_iter() { if let Some(pos) = other.iter().position(|b| a == *b) { other.remove(pos); } else { out.push(a); } } out.append(&mut other); out } } // ------------------------------ pub trait Intersect { fn intersect(self, other: Vec) -> Vec; } impl Intersect for Vec { fn intersect(self, other: Vec) -> Vec { let mut out = Vec::new(); let mut other: Vec<_> = other.into_iter().collect(); for a in self.into_iter() { if let Some(pos) = other.iter().position(|b| a == *b) { out.push(a); other.remove(pos); } } out } } // ------------------------------ pub trait Union { fn union(self, other: Vec) -> Vec; } impl Union for Vec { fn union(mut self, mut other: Vec) -> Vec { self.append(&mut other); self.uniq() } } // ------------------------------ pub trait Uniq { fn uniq(self) -> Vec; } impl Uniq for Vec { fn uniq(mut self) -> Vec { for x in (0..self.len()).rev() { for y in (x + 1..self.len()).rev() { if self[x] == self[y] { self.remove(y); } } } self } } // ------------------------------ pub fn array(i: &str) -> IResult<&str, Array> { let (i, _) = char('[')(i)?; let (i, _) = mightbespace(i)?; let (i, v) = separated_list0(commas, item)(i)?; let (i, _) = mightbespace(i)?; let (i, _) = opt(char(','))(i)?; let (i, _) = mightbespace(i)?; let (i, _) = char(']')(i)?; Ok(( i, Array { value: v, }, )) } fn item(i: &str) -> IResult<&str, Value> { let (i, v) = value(i)?; Ok((i, v)) } #[cfg(test)] mod tests { use super::*; #[test] fn array_normal() { let sql = "[1,2,3]"; let res = array(sql); assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("[1, 2, 3]", format!("{}", out)); assert_eq!(out.value.len(), 3); } #[test] fn array_commas() { let sql = "[1,2,3,]"; let res = array(sql); assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("[1, 2, 3]", format!("{}", out)); assert_eq!(out.value.len(), 3); } #[test] fn array_expression() { let sql = "[1,2,3+1]"; let res = array(sql); assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("[1, 2, 3 + 1]", format!("{}", out)); assert_eq!(out.value.len(), 3); } }