pub use std::collections::*;
pub use std::convert::*;
pub use std::fmt::*;
pub use std::hash::*;
use std::io::BufReader;
pub use std::iter::*;
pub use calamine::*;
pub use calamine::DataType::Bool as ExBool;
pub use calamine::DataType::DateTime as ExDateTime;
pub use calamine::DataType::Empty as ExEmpty;
pub use calamine::DataType::Error as ExError;
pub use calamine::DataType::Float as ExFloat;
pub use calamine::DataType::Int as ExInt;
pub use calamine::DataType::String as ExString;
pub use calamine::DataType;
pub use calamine::Range;
pub use calamine::Sheets;
pub use calamine::{open_workbook, Xlsx, Reader};
pub use std::io::{self, Result as IoResult};
pub use ::serde::*;
pub use serde_json::*;
pub use chrono::prelude::*;
pub use chrono::*;
pub use plotly::common::Mode::*;
pub use plotly::common::*;
pub use plotly::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Out<T> {
Ok(T),
Err(Ex),
}
impl Display for Out<String> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Out::Ok(s) => write!(f, "{}", s),
Out::Err(e) => write!(f, "{}", e),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Ex {
NotFound(String),
Invalid(String),
Other(String),
}
impl Display for Ex {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Ex::NotFound(s) => write!(f, "Not Found: {}", s),
Ex::Invalid(s) => write!(f, "Invalid: {}", s),
Ex::Other(s) => write!(f, "Other: {}", s),
}
}
}
impl<T> Out<T> {
pub fn unwrap(self) -> T {
match self {
Out::Ok(t) => t,
Out::Err(e) => panic!("{}", e),
}
}
}
impl<T> From<std::result::Result<T, &str>> for Out<T> {
fn from(result: std::result::Result<T, &str>) -> Self {
match result {
std::result::Result::Ok(t) => Out::Ok(t),
std::result::Result::Err(e) => Out::Err(Ex::Other(e.to_string())),
}
}
}
impl<T> From<std::result::Result<T, calamine::Error>> for Out<T> {
fn from(result: std::result::Result<T, calamine::Error>) -> Self {
match result {
std::result::Result::Ok(t) => Out::Ok(t),
std::result::Result::Err(e) => Out::Err(Ex::Other(e.to_string())),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Grid {
inner: Vec<Vec<Value>>
}
impl Grid {
pub fn new()->Self{
Self{
inner:Vec::new()
}
}
pub fn from_vec(vec:Vec<Vec<Value>>)->Self{
Self{
inner:vec
}
}
pub fn open(path:&str)->Out<Self>{
let extension = path.split(".").last().unwrap();
match extension {
"xlsx" => Self::open_xlsx(path),
_ => Out::Err(Ex::Invalid("Invalid extension".to_string()))
}
}
pub fn open_xlsx(path:&str)->Out<Self>{
let mut grid = Self::new();
let mut workbook: Xlsx<_> = open_workbook(path).unwrap();
let sheets = workbook.sheet_names().to_owned();
for sheet in sheets {
let mut sheet = workbook.worksheet_range(&sheet).unwrap();
let rows = sheet.unwrap();
let rows = rows.rows();
for row in rows {
let mut row_vec = Vec::new();
for cell in row {
row_vec.push(cell.to_value());
}
grid.inner.push(row_vec);
}
}
Out::Ok(grid)
}
pub fn get_row(&self, index:usize)->Out<Vec<Value>>{
if index < self.inner.len(){
Out::Ok(self.inner[index].clone())
}else{
Out::Err(Ex::NotFound("Row not found".to_string()))
}
}
pub fn get_column(&self, index:usize)->Out<Vec<Value>>{
let mut column = Vec::new();
for row in &self.inner{
if index < row.len(){
column.push(row[index].clone());
}else{
return Out::Err(Ex::NotFound("Column not found".to_string()));
}
}
Out::Ok(column)
}
pub fn get_cell(&self, row:usize, column:usize)->Out<Value>{
if row < self.inner.len(){
if column < self.inner[row].len(){
Out::Ok(self.inner[row][column].clone())
}else{
Out::Err(Ex::NotFound("Column not found".to_string()))
}
}else{
Out::Err(Ex::NotFound("Row not found".to_string()))
}
}
pub fn header(&self)->Out<Vec<String>>{
if self.inner.len() > 0{
let mut header = Vec::new();
for cell in &self.inner[0]{
header.push(cell.to_string());
}
Out::Ok(header)
}else{
Out::Err(Ex::NotFound("Header not found".to_string()))
}
}
pub fn head(&self, n:usize)->Out<Self>{
if self.inner.len() > n{
let mut grid = Self::new();
for i in 0..n{
grid.inner.push(self.inner[i].clone());
}
Out::Ok(grid)
}else{
Out::Err(Ex::NotFound("Head not found".to_string()))
}
}
pub fn tail(&self, n:usize)->Out<Self>{
if self.inner.len() > n{
let mut grid = Self::new();
for i in self.inner.len()-n..self.inner.len(){
grid.inner.push(self.inner[i].clone());
}
Out::Ok(grid)
}else{
Out::Err(Ex::NotFound("Tail not found".to_string()))
}
}
pub fn slice(&self, start:usize, end:usize)->Out<Self>{
if self.inner.len() > end{
let mut grid = Self::new();
for i in start..end{
grid.inner.push(self.inner[i].clone());
}
Out::Ok(grid)
}else{
Out::Err(Ex::NotFound("Slice not found".to_string()))
}
}
pub fn rows(&self)->Out<usize>{
Out::Ok(self.inner.len())
}
pub fn columns(&self)->Out<usize>{
if self.inner.len() > 0{
Out::Ok(self.inner[0].len())
}else{
Out::Err(Ex::NotFound("Columns not found".to_string()))
}
}
pub fn shape(&self)->Out<(usize, usize)>{
if self.inner.len() > 0{
Out::Ok((self.inner.len(), self.inner[0].len()))
}else{
Out::Err(Ex::NotFound("Shape not found".to_string()))
}
}
pub fn plot(&self, xtransform:Fx, ytransform:Fx)->Out<Plot>{
let mut plot = Plot::new();
let mut x = Vec::new();
let mut y = Vec::new();
for row in &self.inner{
x.push(xtransform(row[0].to_value()));
y.push(ytransform(row[1].to_value()));
}
plot.add_trace(Scatter::new(x, y).mode(Markers));
Out::Ok(plot)
}
}
pub type Fx = fn(Value)->f64;
pub trait ToValue {
fn to_value(&self) -> Value;
}
pub trait FromValue {
fn from_value(value: &Value) -> Self;
}
impl FromValue for bool {
fn from_value(value: &Value) -> Self {
match value {
Value::Bool(b) => *b,
_ => false,
}
}
}
impl FromValue for f64 {
fn from_value(value: &Value) -> Self {
match value {
Value::Number(n) => n.as_f64().unwrap(),
_ => 0.0,
}
}
}
impl FromValue for i64 {
fn from_value(value: &Value) -> Self {
match value {
Value::Number(n) => n.as_f64().unwrap() as i64,
_ => 0,
}
}
}
impl FromValue for String {
fn from_value(value: &Value) -> Self {
match value {
Value::String(s) => s.clone(),
_ => "".to_string(),
}
}
}
impl FromValue for DateTime<Utc> {
fn from_value(value: &Value) -> Self {
match value {
Value::String(s) => {
let s = s.split(" ").collect::<Vec<&str>>();
let date = s[0];
let time = s[1];
let date = date.split("-").collect::<Vec<&str>>();
let year = date[0].parse::<i32>().unwrap();
let month = date[1].parse::<u32>().unwrap();
let day = date[2].parse::<u32>().unwrap();
let time = time.split(":").collect::<Vec<&str>>();
let hour = time[0].parse::<u32>().unwrap();
let minute = time[1].parse::<u32>().unwrap();
let second = time[2].parse::<u32>().unwrap();
Utc.ymd(year, month, day).and_hms(hour, minute, second)
}
_ => Utc::now(),
}
}
}
impl FromValue for Value {
fn from_value(value: &Value) -> Self {
value.clone()
}
}
impl FromValue for DataType {
fn from_value(value: &Value) -> Self {
match value {
Value::Bool(b) => DataType::Bool(*b),
Value::Null => DataType::Empty,
Value::Number(n) => DataType::Float(n.as_f64().unwrap()),
Value::String(s) => DataType::String(s.clone()),
_ => DataType::Empty,
}
}
}
impl FromValue for Vec<Value> {
fn from_value(value: &Value) -> Self {
match value {
Value::Array(a) => a.clone(),
_ => Vec::new(),
}
}
}
impl FromValue for Vec<DataType> {
fn from_value(value: &Value) -> Self {
match value {
Value::Array(a) => {
let mut vec = Vec::new();
for value in a {
vec.push(DataType::from_value(value));
}
vec
}
_ => Vec::new(),
}
}
}
impl FromValue for Vec<String> {
fn from_value(value: &Value) -> Self {
match value {
Value::Array(a) => {
let mut vec = Vec::new();
for value in a {
vec.push(String::from_value(value));
}
vec
}
_ => Vec::new(),
}
}
}
impl FromValue for Vec<f64> {
fn from_value(value: &Value) -> Self {
match value {
Value::Array(a) => {
let mut vec = Vec::new();
for value in a {
vec.push(f64::from_value(value));
}
vec
}
_ => Vec::new(),
}
}
}
impl FromValue for Vec<i64> {
fn from_value(value: &Value) -> Self {
match value {
Value::Array(a) => {
let mut vec = Vec::new();
for value in a {
vec.push(i64::from_value(value));
}
vec
}
_ => Vec::new(),
}
}
}
impl ToValue for Value {
fn to_value(&self) -> Value {
self.clone()
}
}
impl ToValue for bool {
fn to_value(&self) -> Value {
Value::Bool(*self)
}
}
impl ToValue for f64 {
fn to_value(&self) -> Value {
Value::Number(Number::from_f64(*self).unwrap())
}
}
impl ToValue for i64 {
fn to_value(&self) -> Value {
Value::Number(Number::from_f64(*self as f64).unwrap())
}
}
impl ToValue for String {
fn to_value(&self) -> Value {
Value::String(self.clone())
}
}
impl ToValue for &str {
fn to_value(&self) -> Value {
Value::String(self.to_string())
}
}
impl ToValue for DataType {
fn to_value(&self) -> Value {
match self {
DataType::Bool(b) => Value::Bool(*b),
DataType::Empty => Value::Null,
DataType::Error(e) => Value::String(e.to_string()),
DataType::Float(f) => Value::Number(Number::from_f64(*f).unwrap()),
DataType::Int(i) => Value::Number(Number::from_f64(*i as f64).unwrap()),
DataType::String(s) => Value::String(s.clone()),
DataType::DateTime(d) => Value::String(d.to_string()),
_ => Value::Null,
}
}
}