Implement SQL Strand as a newtype tuple struct
This commit is contained in:
parent
ed92fb4d85
commit
1ed5df005e
13 changed files with 118 additions and 118 deletions
|
@ -9,7 +9,7 @@ use sha2::Sha512;
|
||||||
|
|
||||||
pub fn md5(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn md5(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let mut hasher = Md5::new();
|
let mut hasher = Md5::new();
|
||||||
hasher.update(args.remove(0).as_strand().as_str());
|
hasher.update(args.remove(0).as_string().as_str());
|
||||||
let val = hasher.finalize();
|
let val = hasher.finalize();
|
||||||
let val = format!("{:x}", val);
|
let val = format!("{:x}", val);
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
|
@ -17,7 +17,7 @@ pub fn md5(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
|
|
||||||
pub fn sha1(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn sha1(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let mut hasher = Sha1::new();
|
let mut hasher = Sha1::new();
|
||||||
hasher.update(args.remove(0).as_strand().as_str());
|
hasher.update(args.remove(0).as_string().as_str());
|
||||||
let val = hasher.finalize();
|
let val = hasher.finalize();
|
||||||
let val = format!("{:x}", val);
|
let val = format!("{:x}", val);
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
|
@ -25,7 +25,7 @@ pub fn sha1(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
|
|
||||||
pub fn sha256(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn sha256(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(args.remove(0).as_strand().as_str());
|
hasher.update(args.remove(0).as_string().as_str());
|
||||||
let val = hasher.finalize();
|
let val = hasher.finalize();
|
||||||
let val = format!("{:x}", val);
|
let val = format!("{:x}", val);
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
|
@ -33,7 +33,7 @@ pub fn sha256(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
|
|
||||||
pub fn sha512(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn sha512(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let mut hasher = Sha512::new();
|
let mut hasher = Sha512::new();
|
||||||
hasher.update(args.remove(0).as_strand().as_str());
|
hasher.update(args.remove(0).as_string().as_str());
|
||||||
let val = hasher.finalize();
|
let val = hasher.finalize();
|
||||||
let val = format!("{:x}", val);
|
let val = format!("{:x}", val);
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
|
@ -52,15 +52,15 @@ pub mod argon2 {
|
||||||
|
|
||||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let algo = Argon2::default();
|
let algo = Argon2::default();
|
||||||
let hash = args.remove(0).as_strand().value;
|
let hash = args.remove(0).as_string();
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let test = PasswordHash::new(&hash).unwrap();
|
let test = PasswordHash::new(&hash).unwrap();
|
||||||
Ok(algo.verify_password(pass.as_ref(), &test).is_ok().into())
|
Ok(algo.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let algo = Argon2::default();
|
let algo = Argon2::default();
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
let hash = algo.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
let hash = algo.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||||
Ok(hash.into())
|
Ok(hash.into())
|
||||||
|
@ -79,14 +79,14 @@ pub mod pbkdf2 {
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let hash = args.remove(0).as_strand().value;
|
let hash = args.remove(0).as_string();
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let test = PasswordHash::new(&hash).unwrap();
|
let test = PasswordHash::new(&hash).unwrap();
|
||||||
Ok(Pbkdf2.verify_password(pass.as_ref(), &test).is_ok().into())
|
Ok(Pbkdf2.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
let hash = Pbkdf2.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
let hash = Pbkdf2.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||||
Ok(hash.into())
|
Ok(hash.into())
|
||||||
|
@ -105,14 +105,14 @@ pub mod scrypt {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let hash = args.remove(0).as_strand().value;
|
let hash = args.remove(0).as_string();
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let test = PasswordHash::new(&hash).unwrap();
|
let test = PasswordHash::new(&hash).unwrap();
|
||||||
Ok(Scrypt.verify_password(pass.as_ref(), &test).is_ok().into())
|
Ok(Scrypt.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let pass = args.remove(0).as_strand().value;
|
let pass = args.remove(0).as_string();
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
let hash = Scrypt.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
let hash = Scrypt.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||||
Ok(hash.into())
|
Ok(hash.into())
|
||||||
|
|
|
@ -14,24 +14,24 @@ use std::char;
|
||||||
#[rustfmt::skip] static LONGITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
#[rustfmt::skip] static LONGITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
||||||
|
|
||||||
pub fn alphanum(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn alphanum(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().all(char::is_alphanumeric).into())
|
Ok(args.remove(0).as_string().chars().all(char::is_alphanumeric).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alpha(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn alpha(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().all(char::is_alphabetic).into())
|
Ok(args.remove(0).as_string().chars().all(char::is_alphabetic).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ascii(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn ascii(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().all(|x| char::is_ascii(&x)).into())
|
Ok(args.remove(0).as_string().chars().all(|x| char::is_ascii(&x)).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(DOMAIN_RE.is_match(args.remove(0).as_strand().as_str()).into())
|
Ok(DOMAIN_RE.is_match(args.remove(0).as_string().as_str()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn email(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn email(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Convert to a &str
|
// Convert to a &str
|
||||||
let val = val.as_str();
|
let val = val.as_str();
|
||||||
// Check if value is empty
|
// Check if value is empty
|
||||||
|
@ -57,25 +57,25 @@ pub fn email(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hexadecimal(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn hexadecimal(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().all(|x| char::is_ascii_hexdigit(&x)).into())
|
Ok(args.remove(0).as_string().chars().all(|x| char::is_ascii_hexdigit(&x)).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn latitude(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn latitude(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(LATITUDE_RE.is_match(args.remove(0).as_strand().as_str()).into())
|
Ok(LATITUDE_RE.is_match(args.remove(0).as_string().as_str()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn longitude(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn longitude(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(LONGITUDE_RE.is_match(args.remove(0).as_strand().as_str()).into())
|
Ok(LONGITUDE_RE.is_match(args.remove(0).as_string().as_str()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn numeric(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn numeric(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().all(char::is_numeric).into())
|
Ok(args.remove(0).as_string().chars().all(char::is_numeric).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn semver(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn semver(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(SEMVER_RE.is_match(args.remove(0).as_strand().as_str()).into())
|
Ok(SEMVER_RE.is_match(args.remove(0).as_string().as_str()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uuid(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn uuid(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(UUID_RE.is_match(args.remove(0).as_strand().as_str()).into())
|
Ok(UUID_RE.is_match(args.remove(0).as_string().as_str()).into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub mod email {
|
||||||
|
|
||||||
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Check if value is empty
|
// Check if value is empty
|
||||||
if val.is_empty() {
|
if val.is_empty() {
|
||||||
return Ok(Value::None);
|
return Ok(Value::None);
|
||||||
|
@ -36,7 +36,7 @@ pub mod email {
|
||||||
|
|
||||||
pub fn user(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn user(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Check if value is empty
|
// Check if value is empty
|
||||||
if val.is_empty() {
|
if val.is_empty() {
|
||||||
return Ok(Value::None);
|
return Ok(Value::None);
|
||||||
|
@ -69,7 +69,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => match v.domain() {
|
Ok(v) => match v.domain() {
|
||||||
|
@ -82,7 +82,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn fragment(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn fragment(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => match v.fragment() {
|
Ok(v) => match v.fragment() {
|
||||||
|
@ -95,7 +95,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn host(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn host(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => match v.host_str() {
|
Ok(v) => match v.host_str() {
|
||||||
|
@ -108,7 +108,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn path(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn path(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => Ok(v.path().into()),
|
Ok(v) => Ok(v.path().into()),
|
||||||
|
@ -118,7 +118,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn port(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn port(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => match v.port() {
|
Ok(v) => match v.port() {
|
||||||
|
@ -131,7 +131,7 @@ pub mod url {
|
||||||
|
|
||||||
pub fn query(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn query(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
// Convert to a String
|
// Convert to a String
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
match Url::parse(&val) {
|
match Url::parse(&val) {
|
||||||
Ok(v) => match v.query() {
|
Ok(v) => match v.query() {
|
||||||
|
|
|
@ -4,51 +4,51 @@ use crate::sql::value::Value;
|
||||||
use slug::slugify;
|
use slug::slugify;
|
||||||
|
|
||||||
pub fn concat(_: &Runtime, args: Vec<Value>) -> Result<Value, Error> {
|
pub fn concat(_: &Runtime, args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.into_iter().map(|x| x.as_strand().value).collect::<Vec<_>>().concat().into())
|
Ok(args.into_iter().map(|x| x.as_string()).collect::<Vec<_>>().concat().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ends_with(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn ends_with(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let chr = args.remove(0).as_strand().value;
|
let chr = args.remove(0).as_string();
|
||||||
Ok(val.ends_with(&chr).into())
|
Ok(val.ends_with(&chr).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn join(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let chr = args.remove(0).as_strand().value;
|
let chr = args.remove(0).as_string();
|
||||||
let val = args.into_iter().map(|x| x.as_strand().value);
|
let val = args.into_iter().map(|x| x.as_string());
|
||||||
let val = val.collect::<Vec<_>>().join(&chr);
|
let val = val.collect::<Vec<_>>().join(&chr);
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn length(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let num = val.chars().count() as i64;
|
let num = val.chars().count() as i64;
|
||||||
Ok(num.into())
|
Ok(num.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lowercase(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn lowercase(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.to_lowercase().into())
|
Ok(args.remove(0).as_string().to_lowercase().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repeat(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn repeat(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let num = args.remove(0).as_int() as usize;
|
let num = args.remove(0).as_int() as usize;
|
||||||
Ok(val.repeat(num).into())
|
Ok(val.repeat(num).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn replace(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let old = args.remove(0).as_strand().value;
|
let old = args.remove(0).as_string();
|
||||||
let new = args.remove(0).as_strand().value;
|
let new = args.remove(0).as_string();
|
||||||
Ok(val.replace(&old, &new).into())
|
Ok(val.replace(&old, &new).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reverse(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn reverse(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.chars().rev().collect::<String>().into())
|
Ok(args.remove(0).as_string().chars().rev().collect::<String>().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn slice(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let beg = args.remove(0).as_int() as usize;
|
let beg = args.remove(0).as_int() as usize;
|
||||||
let lim = args.remove(0).as_int() as usize;
|
let lim = args.remove(0).as_int() as usize;
|
||||||
let val = val.chars().skip(beg).take(lim).collect::<String>();
|
let val = val.chars().skip(beg).take(lim).collect::<String>();
|
||||||
|
@ -56,30 +56,30 @@ pub fn slice(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slug(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn slug(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(slugify(&args.remove(0).as_strand().value).into())
|
Ok(slugify(&args.remove(0).as_string()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn split(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let chr = args.remove(0).as_strand().value;
|
let chr = args.remove(0).as_string();
|
||||||
let val = val.split(&chr).collect::<Vec<&str>>();
|
let val = val.split(&chr).collect::<Vec<&str>>();
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn starts_with(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn starts_with(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let val = args.remove(0).as_strand().value;
|
let val = args.remove(0).as_string();
|
||||||
let chr = args.remove(0).as_strand().value;
|
let chr = args.remove(0).as_string();
|
||||||
Ok(val.starts_with(&chr).into())
|
Ok(val.starts_with(&chr).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trim(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn trim(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.trim().into())
|
Ok(args.remove(0).as_string().trim().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uppercase(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn uppercase(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.to_uppercase().into())
|
Ok(args.remove(0).as_string().to_uppercase().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn words(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn words(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
Ok(args.remove(0).as_strand().value.split(' ').collect::<Vec<&str>>().into())
|
Ok(args.remove(0).as_string().split(' ').collect::<Vec<&str>>().into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub fn floor(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
pub fn group(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
pub fn group(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
match args.remove(0) {
|
match args.remove(0) {
|
||||||
Value::Datetime(v) => match args.remove(0) {
|
Value::Datetime(v) => match args.remove(0) {
|
||||||
Value::Strand(g) => match g.value.as_str() {
|
Value::Strand(g) => match g.as_str() {
|
||||||
"year" => Ok(Utc.ymd(v.value.year(), 1, 1).and_hms(0, 0, 0).into()),
|
"year" => Ok(Utc.ymd(v.value.year(), 1, 1).and_hms(0, 0, 0).into()),
|
||||||
"month" => Ok(Utc.ymd(v.value.year(), v.value.month(), 1).and_hms(0, 0, 0).into()),
|
"month" => Ok(Utc.ymd(v.value.year(), v.value.month(), 1).and_hms(0, 0, 0).into()),
|
||||||
"day" => Ok(Utc
|
"day" => Ok(Utc
|
||||||
|
|
|
@ -100,12 +100,12 @@ pub fn thing(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||||
let tb = args.remove(0);
|
let tb = args.remove(0);
|
||||||
match args.remove(0) {
|
match args.remove(0) {
|
||||||
Value::Thing(id) => Ok(Value::Thing(Thing {
|
Value::Thing(id) => Ok(Value::Thing(Thing {
|
||||||
tb: tb.as_strand().value,
|
tb: tb.as_string(),
|
||||||
id: id.id,
|
id: id.id,
|
||||||
})),
|
})),
|
||||||
id => Ok(Value::Thing(Thing {
|
id => Ok(Value::Thing(Thing {
|
||||||
tb: tb.as_strand().value,
|
tb: tb.as_string(),
|
||||||
id: id.as_strand().into(),
|
id: id.as_string().into(),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::sql::common::val_char;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::ident::ident_raw;
|
use crate::sql::ident::ident_raw;
|
||||||
use crate::sql::number::{number, Number};
|
use crate::sql::number::{number, Number};
|
||||||
use crate::sql::strand::Strand;
|
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::combinator::map;
|
use nom::combinator::map;
|
||||||
|
@ -29,12 +28,6 @@ impl From<String> for Id {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Strand> for Id {
|
|
||||||
fn from(v: Strand) -> Self {
|
|
||||||
Id::String(v.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Id {
|
impl From<&str> for Id {
|
||||||
fn from(v: &str) -> Self {
|
fn from(v: &str) -> Self {
|
||||||
Id::String(v.to_owned())
|
Id::String(v.to_owned())
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl Default for Op {
|
||||||
|
|
||||||
impl From<&Value> for Op {
|
impl From<&Value> for Op {
|
||||||
fn from(v: &Value) -> Self {
|
fn from(v: &Value) -> Self {
|
||||||
match &v.to_strand().value[..] {
|
match v.to_strand().as_str() {
|
||||||
"add" => Op::Add,
|
"add" => Op::Add,
|
||||||
"remove" => Op::Remove,
|
"remove" => Op::Remove,
|
||||||
"replace" => Op::Replace,
|
"replace" => Op::Replace,
|
||||||
|
|
|
@ -4,10 +4,10 @@ use nom::bytes::complete::escaped;
|
||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::character::complete::one_of;
|
use nom::character::complete::one_of;
|
||||||
use serde::ser::SerializeStruct;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
const SINGLE: &str = r#"'"#;
|
const SINGLE: &str = r#"'"#;
|
||||||
|
@ -17,35 +17,39 @@ const DOUBLE: &str = r#"""#;
|
||||||
const DOUBLE_ESC: &str = r#"\""#;
|
const DOUBLE_ESC: &str = r#"\""#;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize)]
|
||||||
pub struct Strand {
|
pub struct Strand(pub String);
|
||||||
pub value: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for Strand {
|
impl From<String> for Strand {
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
Strand {
|
Strand(s)
|
||||||
value: s,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Strand {
|
impl<'a> From<&'a str> for Strand {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
Strand {
|
Strand(String::from(s))
|
||||||
value: String::from(s),
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for Strand {
|
||||||
|
type Target = String;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Strand {
|
impl Strand {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
self.value.as_str()
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
pub fn as_string(self) -> String {
|
||||||
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Strand {
|
impl fmt::Display for Strand {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "\"{}\"", self.value)
|
write!(f, "\"{}\"", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,11 +59,9 @@ impl Serialize for Strand {
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
if serializer.is_human_readable() {
|
if serializer.is_human_readable() {
|
||||||
serializer.serialize_some(&self.value)
|
serializer.serialize_some(&self.0)
|
||||||
} else {
|
} else {
|
||||||
let mut val = serializer.serialize_struct("Strand", 1)?;
|
serializer.serialize_newtype_struct("Strand", &self.0)
|
||||||
val.serialize_field("value", &self.value)?;
|
|
||||||
val.end()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,13 +69,13 @@ impl Serialize for Strand {
|
||||||
impl ops::Add for Strand {
|
impl ops::Add for Strand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn add(self, other: Self) -> Self {
|
fn add(self, other: Self) -> Self {
|
||||||
Strand::from(self.value + &other.value)
|
Strand::from(self.0 + &other.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strand(i: &str) -> IResult<&str, Strand> {
|
pub fn strand(i: &str) -> IResult<&str, Strand> {
|
||||||
let (i, v) = strand_raw(i)?;
|
let (i, v) = strand_raw(i)?;
|
||||||
Ok((i, Strand::from(v)))
|
Ok((i, Strand(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strand_raw(i: &str) -> IResult<&str, String> {
|
pub fn strand_raw(i: &str) -> IResult<&str, String> {
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::sql::common::escape;
|
||||||
use crate::sql::common::val_char;
|
use crate::sql::common::val_char;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::ident::ident_raw;
|
use crate::sql::ident::ident_raw;
|
||||||
use crate::sql::strand::Strand;
|
|
||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -33,12 +32,6 @@ impl From<String> for Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Strand> for Table {
|
|
||||||
fn from(v: Strand) -> Self {
|
|
||||||
Table(v.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Table {
|
impl Deref for Table {
|
||||||
type Target = String;
|
type Target = String;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl Value {
|
||||||
path,
|
path,
|
||||||
value: {
|
value: {
|
||||||
let mut dmp = dmp::new();
|
let mut dmp = dmp::new();
|
||||||
let mut pch = dmp.patch_make1(&a.value, &b.value);
|
let mut pch = dmp.patch_make1(a, b);
|
||||||
let txt = dmp.patch_to_text(&mut pch);
|
let txt = dmp.patch_to_text(&mut pch);
|
||||||
txt.into()
|
txt.into()
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,8 +26,8 @@ impl Value {
|
||||||
if let Value::Strand(p) = o.value {
|
if let Value::Strand(p) = o.value {
|
||||||
if let Value::Strand(v) = self.get(ctx, opt, txn, &o.path).await? {
|
if let Value::Strand(v) = self.get(ctx, opt, txn, &o.path).await? {
|
||||||
let mut dmp = dmp::new();
|
let mut dmp = dmp::new();
|
||||||
let mut pch = dmp.patch_from_text(p.value);
|
let mut pch = dmp.patch_from_text(p.as_string());
|
||||||
let (txt, _) = dmp.patch_apply(&mut pch, &v.value);
|
let (txt, _) = dmp.patch_apply(&mut pch, v.as_str());
|
||||||
let txt = txt.into_iter().collect::<String>();
|
let txt = txt.into_iter().collect::<String>();
|
||||||
self.set(ctx, opt, txn, &o.path, Value::from(txt)).await?;
|
self.set(ctx, opt, txn, &o.path, Value::from(txt)).await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,7 +479,7 @@ impl Value {
|
||||||
pub fn is_true(&self) -> bool {
|
pub fn is_true(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::True => true,
|
Value::True => true,
|
||||||
Value::Strand(v) => v.value.to_ascii_lowercase() == "true",
|
Value::Strand(v) => v.to_ascii_lowercase() == "true",
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ impl Value {
|
||||||
pub fn is_false(&self) -> bool {
|
pub fn is_false(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::False => true,
|
Value::False => true,
|
||||||
Value::Strand(v) => v.value.to_ascii_lowercase() == "false",
|
Value::Strand(v) => v.to_ascii_lowercase() == "false",
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ impl Value {
|
||||||
Value::Geometry(_) => true,
|
Value::Geometry(_) => true,
|
||||||
Value::Array(v) => !v.is_empty(),
|
Value::Array(v) => !v.is_empty(),
|
||||||
Value::Object(v) => !v.is_empty(),
|
Value::Object(v) => !v.is_empty(),
|
||||||
Value::Strand(v) => !v.value.is_empty() && v.value.to_ascii_lowercase() != "false",
|
Value::Strand(v) => !v.is_empty() && v.to_ascii_lowercase() != "false",
|
||||||
Value::Number(v) => v.is_truthy(),
|
Value::Number(v) => v.is_truthy(),
|
||||||
Value::Duration(v) => v.value.as_nanos() > 0,
|
Value::Duration(v) => v.value.as_nanos() > 0,
|
||||||
Value::Datetime(v) => v.value.timestamp() > 0,
|
Value::Datetime(v) => v.value.timestamp() > 0,
|
||||||
|
@ -549,7 +549,7 @@ impl Value {
|
||||||
pub fn as_int(self) -> i64 {
|
pub fn as_int(self) -> i64 {
|
||||||
match self {
|
match self {
|
||||||
Value::True => 1,
|
Value::True => 1,
|
||||||
Value::Strand(v) => v.value.parse::<i64>().unwrap_or(0),
|
Value::Strand(v) => v.parse::<i64>().unwrap_or(0),
|
||||||
Value::Number(v) => v.as_int(),
|
Value::Number(v) => v.as_int(),
|
||||||
Value::Duration(v) => v.value.as_secs() as i64,
|
Value::Duration(v) => v.value.as_secs() as i64,
|
||||||
Value::Datetime(v) => v.value.timestamp(),
|
Value::Datetime(v) => v.value.timestamp(),
|
||||||
|
@ -560,7 +560,7 @@ impl Value {
|
||||||
pub fn as_float(self) -> f64 {
|
pub fn as_float(self) -> f64 {
|
||||||
match self {
|
match self {
|
||||||
Value::True => 1.0,
|
Value::True => 1.0,
|
||||||
Value::Strand(v) => v.value.parse::<f64>().unwrap_or(0.0),
|
Value::Strand(v) => v.parse::<f64>().unwrap_or(0.0),
|
||||||
Value::Number(v) => v.as_float(),
|
Value::Number(v) => v.as_float(),
|
||||||
Value::Duration(v) => v.value.as_secs() as f64,
|
Value::Duration(v) => v.value.as_secs() as f64,
|
||||||
Value::Datetime(v) => v.value.timestamp() as f64,
|
Value::Datetime(v) => v.value.timestamp() as f64,
|
||||||
|
@ -590,13 +590,6 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_string(self) -> String {
|
|
||||||
match self {
|
|
||||||
Value::Strand(v) => v.value,
|
|
||||||
_ => self.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_strand(self) -> Strand {
|
pub fn as_strand(self) -> Strand {
|
||||||
match self {
|
match self {
|
||||||
Value::Strand(v) => v,
|
Value::Strand(v) => v,
|
||||||
|
@ -620,6 +613,13 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_string(self) -> String {
|
||||||
|
match self {
|
||||||
|
Value::Strand(v) => v.as_string(),
|
||||||
|
_ => self.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Expensive conversion of value
|
// Expensive conversion of value
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
@ -660,7 +660,7 @@ impl Value {
|
||||||
|
|
||||||
pub fn to_idiom(&self) -> Idiom {
|
pub fn to_idiom(&self) -> Idiom {
|
||||||
self.to_strand()
|
self.to_strand()
|
||||||
.value
|
.as_str()
|
||||||
.trim_start_matches('/')
|
.trim_start_matches('/')
|
||||||
.split(&['.', '/'][..])
|
.split(&['.', '/'][..])
|
||||||
.map(Part::from)
|
.map(Part::from)
|
||||||
|
@ -854,7 +854,7 @@ impl Value {
|
||||||
match self {
|
match self {
|
||||||
Value::Strand(v) => match other {
|
Value::Strand(v) => match other {
|
||||||
Value::Strand(w) => MATCHER.fuzzy_match(v.as_str(), w.as_str()).is_some(),
|
Value::Strand(w) => MATCHER.fuzzy_match(v.as_str(), w.as_str()).is_some(),
|
||||||
_ => MATCHER.fuzzy_match(v.as_str(), other.to_strand().as_str()).is_some(),
|
_ => MATCHER.fuzzy_match(v.as_str(), other.to_string().as_str()).is_some(),
|
||||||
},
|
},
|
||||||
_ => self.equal(other),
|
_ => self.equal(other),
|
||||||
}
|
}
|
||||||
|
@ -878,8 +878,8 @@ impl Value {
|
||||||
match self {
|
match self {
|
||||||
Value::Array(v) => v.iter().any(|v| v.equal(other)),
|
Value::Array(v) => v.iter().any(|v| v.equal(other)),
|
||||||
Value::Strand(v) => match other {
|
Value::Strand(v) => match other {
|
||||||
Value::Strand(w) => v.value.contains(w.as_str()),
|
Value::Strand(w) => v.contains(w.as_str()),
|
||||||
_ => v.value.contains(&other.to_strand().as_str()),
|
_ => v.contains(&other.to_string().as_str()),
|
||||||
},
|
},
|
||||||
Value::Geometry(v) => match other {
|
Value::Geometry(v) => match other {
|
||||||
Value::Geometry(w) => v.contains(w),
|
Value::Geometry(w) => v.contains(w),
|
||||||
|
@ -927,27 +927,21 @@ impl Value {
|
||||||
|
|
||||||
pub fn lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
pub fn lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Strand(a), Value::Strand(b)) => {
|
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::lexical_cmp(a, b)),
|
||||||
Some(lexical_sort::lexical_cmp(&a.value, &b.value))
|
|
||||||
}
|
|
||||||
_ => self.partial_cmp(other),
|
_ => self.partial_cmp(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn natural_cmp(&self, other: &Value) -> Option<Ordering> {
|
pub fn natural_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Strand(a), Value::Strand(b)) => {
|
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::natural_cmp(a, b)),
|
||||||
Some(lexical_sort::natural_cmp(&a.value, &b.value))
|
|
||||||
}
|
|
||||||
_ => self.partial_cmp(other),
|
_ => self.partial_cmp(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn natural_lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
pub fn natural_lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Strand(a), Value::Strand(b)) => {
|
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::natural_lexical_cmp(a, b)),
|
||||||
Some(lexical_sort::natural_lexical_cmp(&a.value, &b.value))
|
|
||||||
}
|
|
||||||
_ => self.partial_cmp(other),
|
_ => self.partial_cmp(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1330,6 +1324,24 @@ mod tests {
|
||||||
assert_eq!(Strand::from("something"), Value::from("something").as_strand());
|
assert_eq!(Strand::from("something"), Value::from("something").as_strand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_string() {
|
||||||
|
assert_eq!(String::from("NONE"), Value::None.as_string());
|
||||||
|
assert_eq!(String::from("NULL"), Value::Null.as_string());
|
||||||
|
assert_eq!(String::from("VOID"), Value::Void.as_string());
|
||||||
|
assert_eq!(String::from("true"), Value::True.as_string());
|
||||||
|
assert_eq!(String::from("false"), Value::False.as_string());
|
||||||
|
assert_eq!(String::from("0"), Value::from(0).as_string());
|
||||||
|
assert_eq!(String::from("1"), Value::from(1).as_string());
|
||||||
|
assert_eq!(String::from("-1"), Value::from(-1).as_string());
|
||||||
|
assert_eq!(String::from("1.1"), Value::from(1.1).as_string());
|
||||||
|
assert_eq!(String::from("-1.1"), Value::from(-1.1).as_string());
|
||||||
|
assert_eq!(String::from("3"), Value::from("3").as_string());
|
||||||
|
assert_eq!(String::from("true"), Value::from("true").as_string());
|
||||||
|
assert_eq!(String::from("false"), Value::from("false").as_string());
|
||||||
|
assert_eq!(String::from("something"), Value::from("something").as_string());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_deserialize() {
|
fn serialize_deserialize() {
|
||||||
let val = Value::parse(
|
let val = Value::parse(
|
||||||
|
|
Loading…
Reference in a new issue