parent
57fd444f4e
commit
7bc4026d05
@ -0,0 +1,272 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "anyhow" |
||||||
|
version = "1.0.38" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "cfg-if" |
||||||
|
version = "1.0.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "either" |
||||||
|
version = "1.6.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "getrandom" |
||||||
|
version = "0.2.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" |
||||||
|
dependencies = [ |
||||||
|
"cfg-if", |
||||||
|
"libc", |
||||||
|
"wasi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "instant" |
||||||
|
version = "0.1.9" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" |
||||||
|
dependencies = [ |
||||||
|
"cfg-if", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "itertools" |
||||||
|
version = "0.10.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" |
||||||
|
dependencies = [ |
||||||
|
"either", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "itoa" |
||||||
|
version = "0.4.7" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "lazy_static" |
||||||
|
version = "1.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "libc" |
||||||
|
version = "0.2.85" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "lock_api" |
||||||
|
version = "0.4.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" |
||||||
|
dependencies = [ |
||||||
|
"scopeguard", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "log" |
||||||
|
version = "0.4.14" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" |
||||||
|
dependencies = [ |
||||||
|
"cfg-if", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "parking_lot" |
||||||
|
version = "0.11.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" |
||||||
|
dependencies = [ |
||||||
|
"instant", |
||||||
|
"lock_api", |
||||||
|
"parking_lot_core", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "parking_lot_core" |
||||||
|
version = "0.8.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" |
||||||
|
dependencies = [ |
||||||
|
"cfg-if", |
||||||
|
"instant", |
||||||
|
"libc", |
||||||
|
"redox_syscall", |
||||||
|
"smallvec", |
||||||
|
"winapi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "proc-macro2" |
||||||
|
version = "1.0.24" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" |
||||||
|
dependencies = [ |
||||||
|
"unicode-xid", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "quote" |
||||||
|
version = "1.0.8" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "redox_syscall" |
||||||
|
version = "0.1.57" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "ryu" |
||||||
|
version = "1.0.5" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "scopeguard" |
||||||
|
version = "1.1.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde" |
||||||
|
version = "1.0.123" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" |
||||||
|
dependencies = [ |
||||||
|
"serde_derive", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde_derive" |
||||||
|
version = "1.0.123" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"syn", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde_json" |
||||||
|
version = "1.0.61" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" |
||||||
|
dependencies = [ |
||||||
|
"itoa", |
||||||
|
"ryu", |
||||||
|
"serde", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "smallvec" |
||||||
|
version = "1.6.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "syn" |
||||||
|
version = "1.0.60" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"unicode-xid", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "thiserror" |
||||||
|
version = "1.0.23" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" |
||||||
|
dependencies = [ |
||||||
|
"thiserror-impl", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "thiserror-impl" |
||||||
|
version = "1.0.23" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"syn", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "unicode-xid" |
||||||
|
version = "0.2.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "uuid" |
||||||
|
version = "0.8.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" |
||||||
|
dependencies = [ |
||||||
|
"getrandom", |
||||||
|
"serde", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "wasi" |
||||||
|
version = "0.10.2+wasi-snapshot-preview1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi" |
||||||
|
version = "0.3.9" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" |
||||||
|
dependencies = [ |
||||||
|
"winapi-i686-pc-windows-gnu", |
||||||
|
"winapi-x86_64-pc-windows-gnu", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-i686-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-x86_64-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "yopa" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"anyhow", |
||||||
|
"itertools", |
||||||
|
"lazy_static", |
||||||
|
"log", |
||||||
|
"parking_lot", |
||||||
|
"serde", |
||||||
|
"serde_json", |
||||||
|
"thiserror", |
||||||
|
"uuid", |
||||||
|
] |
@ -0,0 +1,192 @@ |
|||||||
|
//! Data value structs
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize}; |
||||||
|
use crate::ID; |
||||||
|
use std::borrow::Cow; |
||||||
|
use crate::StorageError; |
||||||
|
use std::num::ParseIntError; |
||||||
|
use crate::model::DataType; |
||||||
|
|
||||||
|
/// Value of a particular type
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize,PartialEq)] |
||||||
|
pub enum TypedValue { |
||||||
|
/// Text
|
||||||
|
String(Cow<'static, str>), |
||||||
|
/// Integer
|
||||||
|
Integer(i64), |
||||||
|
/// Floating point number
|
||||||
|
Decimal(f64), |
||||||
|
/// Boolean yes/no
|
||||||
|
Boolean(bool), |
||||||
|
} |
||||||
|
|
||||||
|
impl TypedValue { |
||||||
|
/// Try ot cast to another type. On error, the original value is returned as Err.
|
||||||
|
pub fn cast_to(self, ty : DataType) -> Result<TypedValue, TypedValue> { |
||||||
|
match (self, ty) { |
||||||
|
// to string
|
||||||
|
(s @ TypedValue::String(_), DataType::String) => Ok(s), |
||||||
|
(TypedValue::Integer(i), DataType::String) => Ok(TypedValue::String(i.to_string().into())), |
||||||
|
(TypedValue::Decimal(f), DataType::String) => Ok(TypedValue::String(f.to_string().into())), |
||||||
|
(TypedValue::Boolean(b), DataType::String) => Ok(TypedValue::String(Cow::Borrowed(if b { "1" } else { "0" }))), |
||||||
|
// to int
|
||||||
|
(TypedValue::String(s), DataType::Integer) => { |
||||||
|
match s.parse::<i64>() { |
||||||
|
Ok(i) => Ok(TypedValue::Integer(i)), |
||||||
|
Err(_) => Err(TypedValue::String(s)) |
||||||
|
} |
||||||
|
}, |
||||||
|
(s @ TypedValue::Integer(_), DataType::Integer) => Ok(s), |
||||||
|
(TypedValue::Decimal(f), DataType::Integer) => Ok(TypedValue::Integer(f.round() as i64)), |
||||||
|
(TypedValue::Boolean(b), DataType::Integer) => Ok(TypedValue::Integer(if b { 1 } else { 0 })), |
||||||
|
// to float
|
||||||
|
(TypedValue::String(s), DataType::Decimal) => { |
||||||
|
match s.parse::<f64>() { |
||||||
|
Ok(i) => Ok(TypedValue::Decimal(i)), |
||||||
|
Err(_) => Err(TypedValue::String(s)) |
||||||
|
} |
||||||
|
}, |
||||||
|
(TypedValue::Integer(i), DataType::Decimal) => Ok(TypedValue::Decimal(i as f64)), |
||||||
|
(d @ TypedValue::Decimal(_), DataType::Decimal) => Ok(d), |
||||||
|
(e @ TypedValue::Boolean(_), DataType::Decimal) => Err(e), |
||||||
|
// to bool
|
||||||
|
(TypedValue::String(s), DataType::Boolean) => { |
||||||
|
match &(&s).to_ascii_lowercase()[..] { |
||||||
|
"y" | "yes" | "true" | "1" => { |
||||||
|
Ok(TypedValue::Boolean(true)) |
||||||
|
} |
||||||
|
"n" | "no" | "false" | "0" => { |
||||||
|
Ok(TypedValue::Boolean(false)) |
||||||
|
} |
||||||
|
_ => { |
||||||
|
Err(TypedValue::String(s)) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
(TypedValue::Integer(i), DataType::Boolean) => Ok(TypedValue::Boolean(i != 0)), |
||||||
|
(e @ TypedValue::Decimal(_), DataType::Boolean) => Err(e), |
||||||
|
(b @ TypedValue::Boolean(_), DataType::Boolean) => Ok(b), |
||||||
|
(s, _) => { |
||||||
|
Err(s) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use crate::TypedValue; |
||||||
|
use crate::model::DataType; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_cast_to_bool() { |
||||||
|
// Cast to bool
|
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::Boolean(true).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::Boolean(false).cast_to(DataType::Boolean)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::Integer(123).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::Integer(0).cast_to(DataType::Boolean)); |
||||||
|
|
||||||
|
assert_eq!(Err(TypedValue::Decimal(0.0)), TypedValue::Decimal(0.0).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Err(TypedValue::Decimal(123.0)), TypedValue::Decimal(123.0).cast_to(DataType::Boolean)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::String("true".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::String("1".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::String("y".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(true)), TypedValue::String("yes".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::String("false".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::String("0".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::String("n".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Ok(TypedValue::Boolean(false)), TypedValue::String("no".into()).cast_to(DataType::Boolean)); |
||||||
|
assert_eq!(Err(TypedValue::String("blorg".into())), TypedValue::String("blorg".into()).cast_to(DataType::Boolean)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_cast_to_int() { |
||||||
|
// Cast to bool
|
||||||
|
assert_eq!(Ok(TypedValue::Integer(1)), TypedValue::Boolean(true).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(0)), TypedValue::Boolean(false).cast_to(DataType::Integer)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Integer(123)), TypedValue::Integer(123).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(0)), TypedValue::Integer(0).cast_to(DataType::Integer)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Integer(0)), TypedValue::Decimal(0.0).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(123)), TypedValue::Decimal(123.0).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(-124)), TypedValue::Decimal(-123.7).cast_to(DataType::Integer)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Integer(123)), TypedValue::String("123".into()).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(-123)), TypedValue::String("-123".into()).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Ok(TypedValue::Integer(0)), TypedValue::String("0".into()).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Err(TypedValue::String("123.456".into())), TypedValue::String("123.456".into()).cast_to(DataType::Integer)); |
||||||
|
assert_eq!(Err(TypedValue::String("-123.456".into())), TypedValue::String("-123.456".into()).cast_to(DataType::Integer)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_cast_to_decimal() { |
||||||
|
// Cast to bool
|
||||||
|
assert_eq!(Err(TypedValue::Boolean(true)), TypedValue::Boolean(true).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Err(TypedValue::Boolean(false)), TypedValue::Boolean(false).cast_to(DataType::Decimal)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Decimal(123.0)), TypedValue::Integer(123).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Ok(TypedValue::Decimal(0.0)), TypedValue::Integer(0).cast_to(DataType::Decimal)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Decimal(0.0)), TypedValue::Decimal(0.0).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Ok(TypedValue::Decimal(-123.7)), TypedValue::Decimal(-123.7).cast_to(DataType::Decimal)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::Decimal(123.0)), TypedValue::String("123".into()).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Ok(TypedValue::Decimal(-123.0)), TypedValue::String("-123".into()).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Ok(TypedValue::Decimal(0.0)), TypedValue::String("0".into()).cast_to(DataType::Decimal)); |
||||||
|
assert_eq!(Ok(TypedValue::Decimal(-123.456)), TypedValue::String("-123.456".into()).cast_to(DataType::Decimal)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_cast_to_string() { |
||||||
|
// Cast to bool
|
||||||
|
assert_eq!(Ok(TypedValue::String("1".into())), TypedValue::Boolean(true).cast_to(DataType::String)); |
||||||
|
assert_eq!(Ok(TypedValue::String("0".into())), TypedValue::Boolean(false).cast_to(DataType::String)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::String("123".into())), TypedValue::Integer(123).cast_to(DataType::String)); |
||||||
|
assert_eq!(Ok(TypedValue::String("0".into())), TypedValue::Integer(0).cast_to(DataType::String)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::String("0".into())), TypedValue::Decimal(0.0).cast_to(DataType::String)); |
||||||
|
assert_eq!(Ok(TypedValue::String("123".into())), TypedValue::Decimal(123.0).cast_to(DataType::String)); |
||||||
|
assert_eq!(Ok(TypedValue::String("-123.5".into())), TypedValue::Decimal(-123.5).cast_to(DataType::String)); |
||||||
|
|
||||||
|
assert_eq!(Ok(TypedValue::String("blorg".into())), TypedValue::String("blorg".into()).cast_to(DataType::String)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Instance of an object
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct Object { |
||||||
|
/// PK
|
||||||
|
pub id : ID, |
||||||
|
/// Object template ID
|
||||||
|
pub model_id: ID, |
||||||
|
} |
||||||
|
|
||||||
|
/// Relation between two objects
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct Relation { |
||||||
|
/// PK
|
||||||
|
pub id : ID, |
||||||
|
/// Source object ID
|
||||||
|
pub object_id : ID, |
||||||
|
/// Relation template ID
|
||||||
|
pub model_id: ID, |
||||||
|
/// Related object ID
|
||||||
|
pub related_id : ID, |
||||||
|
} |
||||||
|
|
||||||
|
/// Value attached to an object
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct Value { |
||||||
|
/// PK
|
||||||
|
pub id : ID, |
||||||
|
/// Owning object ID
|
||||||
|
pub object_id : ID, |
||||||
|
/// Property template ID
|
||||||
|
pub model_id: ID, |
||||||
|
/// Property value
|
||||||
|
pub value : TypedValue, |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
//! Helper struct for inserting relational data in the database
|
||||||
|
|
||||||
|
use super::ID; |
||||||
|
use super::data::TypedValue; |
||||||
|
use serde::{Serialize,Deserialize}; |
||||||
|
|
||||||
|
/// Value to insert
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct InsertValue { |
||||||
|
pub model_id: ID, |
||||||
|
pub value: TypedValue |
||||||
|
} |
||||||
|
|
||||||
|
impl InsertValue { |
||||||
|
pub fn new(model_id : ID, value : TypedValue) -> Self { |
||||||
|
Self { |
||||||
|
model_id, |
||||||
|
value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Info for inserting a relation
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct InsertRel { |
||||||
|
pub model_id: ID, |
||||||
|
pub related_id: ID, |
||||||
|
pub values: Vec<InsertValue> |
||||||
|
} |
||||||
|
|
||||||
|
impl InsertRel { |
||||||
|
pub fn new(model_id : ID, related_id: ID, values : Vec<InsertValue>) -> Self { |
||||||
|
Self { |
||||||
|
model_id, |
||||||
|
related_id, |
||||||
|
values |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Info for inserting a relation
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct InsertObj { |
||||||
|
pub model_id: ID, |
||||||
|
pub values: Vec<InsertValue>, |
||||||
|
pub relations: Vec<InsertRel>, |
||||||
|
} |
||||||
|
|
||||||
|
impl InsertObj { |
||||||
|
pub fn new(model_id : ID, values : Vec<InsertValue>, relations: Vec<InsertRel>) -> Self { |
||||||
|
Self { |
||||||
|
model_id, |
||||||
|
values, |
||||||
|
relations |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
//! Data model structs and enums
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize}; |
||||||
|
use std::borrow::Cow; |
||||||
|
use super::ID; |
||||||
|
use super::data::TypedValue; |
||||||
|
use std::fmt::{Display, Formatter}; |
||||||
|
use std::fmt; |
||||||
|
|
||||||
|
/// Get a description of a struct
|
||||||
|
pub trait Describe { |
||||||
|
/// Short but informative description for error messages
|
||||||
|
fn describe(&self) -> String; |
||||||
|
} |
||||||
|
|
||||||
|
/// Object template
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct ObjectModel { |
||||||
|
/// PK
|
||||||
|
pub id : ID, |
||||||
|
/// Template name, unique within the database
|
||||||
|
pub name: String, |
||||||
|
/// Parent object template ID
|
||||||
|
pub parent_tpl_id: Option<ID>, |
||||||
|
} |
||||||
|
|
||||||
|
/// Relation between templates
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct RelationModel { |
||||||
|
/// PK
|
||||||
|
pub id: ID, |
||||||
|
/// Object template ID
|
||||||
|
pub object_tpl_id: ID, |
||||||
|
/// Relation name, unique within the parent object
|
||||||
|
pub name: String, |
||||||
|
/// Relation is optional
|
||||||
|
pub optional: bool, |
||||||
|
/// Relation can be multiple
|
||||||
|
pub multiple: bool, |
||||||
|
/// Related object template ID
|
||||||
|
pub related_tpl_id: ID, |
||||||
|
} |
||||||
|
|
||||||
|
/// Property definition
|
||||||
|
#[derive(Debug,Clone,Serialize,Deserialize)] |
||||||
|
pub struct PropertyModel { |
||||||
|
/// PK
|
||||||
|
pub id: ID, |
||||||
|
/// Object or Reference template ID
|
||||||
|
pub parent_tpl_id: ID, |
||||||
|
/// Property name, unique within the parent object or reference
|
||||||
|
pub name: String, |
||||||
|
/// Property is optional
|
||||||
|
pub optional: bool, |
||||||
|
/// Property can be multiple
|
||||||
|
pub multiple: bool, |
||||||
|
/// Property data type
|
||||||
|
pub data_type: DataType, |
||||||
|
/// Default value, used for newly created objects
|
||||||
|
pub default: Option<TypedValue>, |
||||||
|
} |
||||||
|
|
||||||
|
/// Value data type
|
||||||
|
#[derive(Debug,Clone,Copy,Serialize,Deserialize,Eq,PartialEq)] |
||||||
|
pub enum DataType { |
||||||
|
/// Text
|
||||||
|
String, |
||||||
|
/// Integer
|
||||||
|
Integer, |
||||||
|
/// Floating point number
|
||||||
|
Decimal, |
||||||
|
/// Boolean yes/no
|
||||||
|
Boolean, |
||||||
|
} |
||||||
|
|
||||||
|
impl Display for ObjectModel { |
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
||||||
|
write!(f, "object \"{}\" ({})", self.name, self.id) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Display for RelationModel { |
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
||||||
|
write!(f, "relation \"{}\" ({})", self.name, self.id) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Display for PropertyModel { |
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
||||||
|
write!(f, "property \"{}\" ({})", self.name, self.id) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue