Skip to content

Commit

Permalink
Add support for complex numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
ly0va committed Dec 4, 2023
1 parent 6af0c06 commit 4aa591a
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 70 deletions.
77 changes: 77 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ thiserror = "1.0"
log = "0.4"
pretty_env_logger = "0.4"
once_cell = "1.15"
num = "0.4.1"

# TODO: feature-gate this
rusqlite = { version = "0.28", features = ["bundled", "column_decltype"] }
Expand Down
18 changes: 12 additions & 6 deletions proto/database.proto
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
syntax = "proto3";
package database;

message StringInvl {
string s1 = 1;
string s2 = 2;
message ComplexInt {
int64 re = 1;
int64 im = 2;
}

message ComplexFloat {
double re = 1;
double im = 2;
}

message TypedValue {
oneof data {
int64 int = 1;
double float = 2;
string string = 3;
StringInvl string_invl = 4;
ComplexInt complex_int = 4;
ComplexFloat complex_float = 5;
}
}

Expand Down Expand Up @@ -53,8 +59,8 @@ message Create {
FLOAT = 1;
CHAR = 2;
STRING = 3;
CHAR_INVL = 4;
STRING_INVL = 5;
COMPLEX_INT = 4;
COMPLEX_FLOAT = 5;
}
string table = 1;
map<string, Type> columns = 2;
Expand Down
116 changes: 60 additions & 56 deletions src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashMap;
use std::fmt;
use std::io;

use num::complex::Complex;
use rusqlite::types::ToSqlOutput;
use serde::{Deserialize, Serialize};
use thiserror::Error;
Expand Down Expand Up @@ -96,8 +97,8 @@ pub enum TypedValue {
Float(f64),
Char(char),
String(String),
CharInvl(char, char),
StringInvl(String, String),
ComplexInt(i64, i64),
ComplexFloat(f64, f64),
}

#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
Expand All @@ -107,8 +108,8 @@ pub enum DataType {
Float = 1,
Char = 2,
String = 3,
CharInvl = 4,
StringInvl = 5,
ComplexInt = 4,
ComplexFloat = 5,
}

impl rusqlite::ToSql for TypedValue {
Expand All @@ -118,27 +119,16 @@ impl rusqlite::ToSql for TypedValue {
TypedValue::Float(f) => f.to_sql(),
TypedValue::String(s) => s.to_sql(),
TypedValue::Char(c) => Ok(ToSqlOutput::from(c.to_string())),
TypedValue::StringInvl(s1, s2) => Ok(ToSqlOutput::from(format!("{}..{}", s1, s2))),
TypedValue::CharInvl(c1, c2) => Ok(ToSqlOutput::from(format!("{}..{}", c1, c2))),
TypedValue::ComplexInt(r, i) => Ok(ToSqlOutput::from(Complex::new(*r, *i).to_string())),
TypedValue::ComplexFloat(r, i) => {
Ok(ToSqlOutput::from(Complex::new(*r, *i).to_string()))
}
}
}
}

impl TypedValue {
pub fn validate(&self) -> Result<(), DobbyError> {
match self {
TypedValue::CharInvl(c1, c2) => {
if c1 > c2 {
return Err(DobbyError::InvalidRange(c1.to_string(), c2.to_string()));
}
}
TypedValue::StringInvl(s1, s2) => {
if s1 > s2 {
return Err(DobbyError::InvalidRange(s1.to_string(), s2.to_string()));
}
}
_ => {}
}
Ok(())
}

Expand All @@ -148,8 +138,8 @@ impl TypedValue {
TypedValue::Float(_) => DataType::Float,
TypedValue::Char(_) => DataType::Char,
TypedValue::String(_) => DataType::String,
TypedValue::CharInvl(_, _) => DataType::CharInvl,
TypedValue::StringInvl(_, _) => DataType::StringInvl,
TypedValue::ComplexInt(_, _) => DataType::ComplexInt,
TypedValue::ComplexFloat(_, _) => DataType::ComplexFloat,
}
}

Expand Down Expand Up @@ -181,11 +171,21 @@ impl TypedValue {
Ok(char::from(buf[0]).into())
}
DataType::String => Ok(TypedValue::String(read_string()?)),
DataType::StringInvl => Ok(TypedValue::StringInvl(read_string()?, read_string()?)),
DataType::CharInvl => {
let mut buf = [0; 2];
DataType::ComplexInt => {
let mut buf = [0; 8];
reader.read_exact(&mut buf)?;
let r = i64::from_le_bytes(buf);
reader.read_exact(&mut buf)?;
let i = i64::from_le_bytes(buf);
Ok(TypedValue::ComplexInt(r, i))
}
DataType::ComplexFloat => {
let mut buf = [0; 8];
reader.read_exact(&mut buf)?;
let r = f64::from_le_bytes(buf);
reader.read_exact(&mut buf)?;
Ok(TypedValue::CharInvl(char::from(buf[0]), char::from(buf[1])))
let i = f64::from_le_bytes(buf);
Ok(TypedValue::ComplexFloat(r, i))
}
}
}
Expand All @@ -202,8 +202,12 @@ impl TypedValue {
TypedValue::Float(f) => f.to_le_bytes().to_vec(),
TypedValue::Char(c) => vec![c as u8],
TypedValue::String(s) => convert_string(s),
TypedValue::CharInvl(c1, c2) => vec![c1 as u8, c2 as u8],
TypedValue::StringInvl(s1, s2) => [convert_string(s1), convert_string(s2)].concat(),
TypedValue::ComplexInt(r, i) => {
[r.to_le_bytes().to_vec(), i.to_le_bytes().to_vec()].concat()
}
TypedValue::ComplexFloat(r, i) => {
[r.to_le_bytes().to_vec(), i.to_le_bytes().to_vec()].concat()
}
}
}

Expand All @@ -230,23 +234,14 @@ impl TypedValue {
.parse::<f64>()
.map(TypedValue::Float)
.map_err(|_| DobbyError::InvalidValue(self, to)),
(TypedValue::String(s), DataType::StringInvl) => {
if let Some((s1, s2)) = s.split_once("..") {
Ok(TypedValue::StringInvl(s1.to_string(), s2.to_string()))
} else {
Err(DobbyError::InvalidValue(self, to))
}
}
(TypedValue::String(s), DataType::CharInvl) => {
if let Some((s1, s2)) = s.split_once("..") {
Ok(TypedValue::CharInvl(
string_to_char(s1)?,
string_to_char(s2)?,
))
} else {
Err(DobbyError::InvalidValue(self, to))
}
}
(TypedValue::String(s), DataType::ComplexInt) => s
.parse::<Complex<i64>>()
.map(|c| TypedValue::ComplexInt(c.re, c.im))
.map_err(|_| DobbyError::InvalidValue(self, to)),
(TypedValue::String(s), DataType::ComplexFloat) => s
.parse::<Complex<f64>>()
.map(|c| TypedValue::ComplexFloat(c.re, c.im))
.map_err(|_| DobbyError::InvalidValue(self, to)),

(TypedValue::Char(c), DataType::String) => Ok(TypedValue::String(c.to_string())),
(TypedValue::Char(c), DataType::Int) => c
Expand All @@ -259,12 +254,21 @@ impl TypedValue {
.parse::<f64>()
.map(TypedValue::Float)
.map_err(|_| DobbyError::InvalidValue(self, to)),
(TypedValue::Char(c), DataType::ComplexInt) => c
.to_string()
.parse::<Complex<i64>>()
.map(|c| TypedValue::ComplexInt(c.re, c.im))
.map_err(|_| DobbyError::InvalidValue(self, to)),
(TypedValue::Char(c), DataType::ComplexFloat) => c
.to_string()
.parse::<Complex<f64>>()
.map(|c| TypedValue::ComplexFloat(c.re, c.im))
.map_err(|_| DobbyError::InvalidValue(self, to)),

(TypedValue::Int(i), DataType::Float) => Ok(TypedValue::Float(*i as f64)),
(TypedValue::StringInvl(s1, s2), DataType::CharInvl) => Ok(TypedValue::CharInvl(
string_to_char(s1)?,
string_to_char(s2)?,
)),
(TypedValue::ComplexInt(r, i), DataType::ComplexFloat) => {
Ok(TypedValue::ComplexFloat(*r as f64, *i as f64))
}
(v, _) => Err(DobbyError::InvalidValue(v.clone(), to)),
}
}
Expand Down Expand Up @@ -307,8 +311,8 @@ impl ToString for TypedValue {
TypedValue::Float(f) => f.to_string(),
TypedValue::Char(c) => c.to_string(),
TypedValue::String(s) => s.to_string(),
TypedValue::CharInvl(c1, c2) => format!("{}..{}", c1, c2),
TypedValue::StringInvl(s1, s2) => format!("{}..{}", s1, s2),
TypedValue::ComplexInt(r, i) => Complex::new(*r, *i).to_string(),
TypedValue::ComplexFloat(r, i) => Complex::new(*r, *i).to_string(),
}
}
}
Expand All @@ -320,8 +324,8 @@ impl fmt::Debug for DataType {
DataType::Float => write!(f, "float"),
DataType::Char => write!(f, "char"),
DataType::String => write!(f, "string"),
DataType::CharInvl => write!(f, "char_invl"),
DataType::StringInvl => write!(f, "string_invl"),
DataType::ComplexInt => write!(f, "complex_int"),
DataType::ComplexFloat => write!(f, "complex_float"),
}
}
}
Expand All @@ -335,8 +339,8 @@ impl TryFrom<&str> for DataType {
"float" => Ok(DataType::Float),
"char" => Ok(DataType::Char),
"string" => Ok(DataType::String),
"char_invl" => Ok(DataType::CharInvl),
"string_invl" => Ok(DataType::StringInvl),
"complex_int" => Ok(DataType::ComplexInt),
"complex_float" => Ok(DataType::ComplexFloat),
_ => Err(DobbyError::InvalidDataType(s.to_string())),
}
}
Expand All @@ -349,8 +353,8 @@ impl From<i32> for DataType {
1 => DataType::Float,
2 => DataType::Char,
3 => DataType::String,
4 => DataType::CharInvl,
5 => DataType::StringInvl,
4 => DataType::ComplexInt,
5 => DataType::ComplexFloat,
_ => unreachable!("Invalid data type"),
}
}
Expand Down
21 changes: 13 additions & 8 deletions src/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ impl From<typed_value::Data> for TypedValue {
typed_value::Data::Int(i) => TypedValue::Int(i),
typed_value::Data::Float(f) => TypedValue::Float(f),
typed_value::Data::String(s) => TypedValue::String(s),
typed_value::Data::StringInvl(i) => TypedValue::StringInvl(i.s1, i.s2),
typed_value::Data::ComplexInt(proto::ComplexInt { re, im }) => {
TypedValue::ComplexInt(re, im)
}
typed_value::Data::ComplexFloat(proto::ComplexFloat { re, im }) => {
TypedValue::ComplexFloat(re, im)
}
}
}
}
Expand All @@ -164,14 +169,14 @@ impl From<TypedValue> for proto::TypedValue {
proto::TypedValue { data: Some(typed_value::Data::String(c.to_string())) }
}
TypedValue::String(s) => proto::TypedValue { data: Some(typed_value::Data::String(s)) },
TypedValue::CharInvl(c1, c2) => proto::TypedValue {
data: Some(typed_value::Data::StringInvl(proto::StringInvl {
s1: c1.to_string(),
s2: c2.to_string(),
})),
TypedValue::ComplexInt(re, im) => proto::TypedValue {
data: Some(typed_value::Data::ComplexInt(proto::ComplexInt { re, im })),
},
TypedValue::StringInvl(s1, s2) => proto::TypedValue {
data: Some(typed_value::Data::StringInvl(proto::StringInvl { s1, s2 })),
TypedValue::ComplexFloat(re, im) => proto::TypedValue {
data: Some(typed_value::Data::ComplexFloat(proto::ComplexFloat {
re,
im,
})),
},
}
}
Expand Down

0 comments on commit 4aa591a

Please sign in to comment.