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> {
|
||||
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 = format!("{:x}", val);
|
||||
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> {
|
||||
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 = format!("{:x}", val);
|
||||
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> {
|
||||
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 = format!("{:x}", val);
|
||||
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> {
|
||||
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 = format!("{:x}", val);
|
||||
Ok(val.into())
|
||||
|
@ -52,15 +52,15 @@ pub mod argon2 {
|
|||
|
||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let algo = Argon2::default();
|
||||
let hash = args.remove(0).as_strand().value;
|
||||
let pass = args.remove(0).as_strand().value;
|
||||
let hash = args.remove(0).as_string();
|
||||
let pass = args.remove(0).as_string();
|
||||
let test = PasswordHash::new(&hash).unwrap();
|
||||
Ok(algo.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||
}
|
||||
|
||||
pub fn gen(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
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 hash = algo.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||
Ok(hash.into())
|
||||
|
@ -79,14 +79,14 @@ pub mod pbkdf2 {
|
|||
use rand::rngs::OsRng;
|
||||
|
||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let hash = args.remove(0).as_strand().value;
|
||||
let pass = args.remove(0).as_strand().value;
|
||||
let hash = args.remove(0).as_string();
|
||||
let pass = args.remove(0).as_string();
|
||||
let test = PasswordHash::new(&hash).unwrap();
|
||||
Ok(Pbkdf2.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||
}
|
||||
|
||||
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 hash = Pbkdf2.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||
Ok(hash.into())
|
||||
|
@ -105,14 +105,14 @@ pub mod scrypt {
|
|||
};
|
||||
|
||||
pub fn cmp(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let hash = args.remove(0).as_strand().value;
|
||||
let pass = args.remove(0).as_strand().value;
|
||||
let hash = args.remove(0).as_string();
|
||||
let pass = args.remove(0).as_string();
|
||||
let test = PasswordHash::new(&hash).unwrap();
|
||||
Ok(Scrypt.verify_password(pass.as_ref(), &test).is_ok().into())
|
||||
}
|
||||
|
||||
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 hash = Scrypt.hash_password(pass.as_ref(), salt.as_ref()).unwrap().to_string();
|
||||
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());
|
||||
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Convert to a &str
|
||||
let val = val.as_str();
|
||||
// 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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Check if value is empty
|
||||
if val.is_empty() {
|
||||
return Ok(Value::None);
|
||||
|
@ -36,7 +36,7 @@ pub mod email {
|
|||
|
||||
pub fn user(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Check if value is empty
|
||||
if val.is_empty() {
|
||||
return Ok(Value::None);
|
||||
|
@ -69,7 +69,7 @@ pub mod url {
|
|||
|
||||
pub fn domain(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => match v.domain() {
|
||||
|
@ -82,7 +82,7 @@ pub mod url {
|
|||
|
||||
pub fn fragment(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => match v.fragment() {
|
||||
|
@ -95,7 +95,7 @@ pub mod url {
|
|||
|
||||
pub fn host(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => match v.host_str() {
|
||||
|
@ -108,7 +108,7 @@ pub mod url {
|
|||
|
||||
pub fn path(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => Ok(v.path().into()),
|
||||
|
@ -118,7 +118,7 @@ pub mod url {
|
|||
|
||||
pub fn port(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => match v.port() {
|
||||
|
@ -131,7 +131,7 @@ pub mod url {
|
|||
|
||||
pub fn query(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
// Convert to a String
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
// Parse the URL
|
||||
match Url::parse(&val) {
|
||||
Ok(v) => match v.query() {
|
||||
|
|
|
@ -4,51 +4,51 @@ use crate::sql::value::Value;
|
|||
use slug::slugify;
|
||||
|
||||
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> {
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let chr = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
let chr = args.remove(0).as_string();
|
||||
Ok(val.ends_with(&chr).into())
|
||||
}
|
||||
|
||||
pub fn join(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let chr = args.remove(0).as_strand().value;
|
||||
let val = args.into_iter().map(|x| x.as_strand().value);
|
||||
let chr = args.remove(0).as_string();
|
||||
let val = args.into_iter().map(|x| x.as_string());
|
||||
let val = val.collect::<Vec<_>>().join(&chr);
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
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;
|
||||
Ok(num.into())
|
||||
}
|
||||
|
||||
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> {
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
let num = args.remove(0).as_int() as usize;
|
||||
Ok(val.repeat(num).into())
|
||||
}
|
||||
|
||||
pub fn replace(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let old = args.remove(0).as_strand().value;
|
||||
let new = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
let old = args.remove(0).as_string();
|
||||
let new = args.remove(0).as_string();
|
||||
Ok(val.replace(&old, &new).into())
|
||||
}
|
||||
|
||||
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> {
|
||||
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 lim = args.remove(0).as_int() as usize;
|
||||
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> {
|
||||
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> {
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let chr = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
let chr = args.remove(0).as_string();
|
||||
let val = val.split(&chr).collect::<Vec<&str>>();
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
pub fn starts_with(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
||||
let val = args.remove(0).as_strand().value;
|
||||
let chr = args.remove(0).as_strand().value;
|
||||
let val = args.remove(0).as_string();
|
||||
let chr = args.remove(0).as_string();
|
||||
Ok(val.starts_with(&chr).into())
|
||||
}
|
||||
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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()),
|
||||
"month" => Ok(Utc.ymd(v.value.year(), v.value.month(), 1).and_hms(0, 0, 0).into()),
|
||||
"day" => Ok(Utc
|
||||
|
|
|
@ -100,12 +100,12 @@ pub fn thing(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
|||
let tb = args.remove(0);
|
||||
match args.remove(0) {
|
||||
Value::Thing(id) => Ok(Value::Thing(Thing {
|
||||
tb: tb.as_strand().value,
|
||||
tb: tb.as_string(),
|
||||
id: id.id,
|
||||
})),
|
||||
id => Ok(Value::Thing(Thing {
|
||||
tb: tb.as_strand().value,
|
||||
id: id.as_strand().into(),
|
||||
tb: tb.as_string(),
|
||||
id: id.as_string().into(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::sql::common::val_char;
|
|||
use crate::sql::error::IResult;
|
||||
use crate::sql::ident::ident_raw;
|
||||
use crate::sql::number::{number, Number};
|
||||
use crate::sql::strand::Strand;
|
||||
use nanoid::nanoid;
|
||||
use nom::branch::alt;
|
||||
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 {
|
||||
fn from(v: &str) -> Self {
|
||||
Id::String(v.to_owned())
|
||||
|
|
|
@ -26,7 +26,7 @@ impl Default for Op {
|
|||
|
||||
impl From<&Value> for Op {
|
||||
fn from(v: &Value) -> Self {
|
||||
match &v.to_strand().value[..] {
|
||||
match v.to_strand().as_str() {
|
||||
"add" => Op::Add,
|
||||
"remove" => Op::Remove,
|
||||
"replace" => Op::Replace,
|
||||
|
|
|
@ -4,10 +4,10 @@ use nom::bytes::complete::escaped;
|
|||
use nom::bytes::complete::is_not;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::one_of;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::ops;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
const SINGLE: &str = r#"'"#;
|
||||
|
@ -17,35 +17,39 @@ const DOUBLE: &str = r#"""#;
|
|||
const DOUBLE_ESC: &str = r#"\""#;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize)]
|
||||
pub struct Strand {
|
||||
pub value: String,
|
||||
}
|
||||
pub struct Strand(pub String);
|
||||
|
||||
impl From<String> for Strand {
|
||||
fn from(s: String) -> Self {
|
||||
Strand {
|
||||
value: s,
|
||||
}
|
||||
Strand(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Strand {
|
||||
fn from(s: &str) -> Self {
|
||||
Strand {
|
||||
value: String::from(s),
|
||||
Strand(String::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Strand {
|
||||
type Target = String;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Strand {
|
||||
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 {
|
||||
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,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
serializer.serialize_some(&self.value)
|
||||
serializer.serialize_some(&self.0)
|
||||
} else {
|
||||
let mut val = serializer.serialize_struct("Strand", 1)?;
|
||||
val.serialize_field("value", &self.value)?;
|
||||
val.end()
|
||||
serializer.serialize_newtype_struct("Strand", &self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,13 +69,13 @@ impl Serialize for Strand {
|
|||
impl ops::Add for Strand {
|
||||
type Output = 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> {
|
||||
let (i, v) = strand_raw(i)?;
|
||||
Ok((i, Strand::from(v)))
|
||||
Ok((i, Strand(v)))
|
||||
}
|
||||
|
||||
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::error::IResult;
|
||||
use crate::sql::ident::ident_raw;
|
||||
use crate::sql::strand::Strand;
|
||||
use nom::multi::separated_list1;
|
||||
use serde::{Deserialize, Serialize};
|
||||
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 {
|
||||
type Target = String;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
|
@ -66,7 +66,7 @@ impl Value {
|
|||
path,
|
||||
value: {
|
||||
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);
|
||||
txt.into()
|
||||
},
|
||||
|
|
|
@ -26,8 +26,8 @@ impl Value {
|
|||
if let Value::Strand(p) = o.value {
|
||||
if let Value::Strand(v) = self.get(ctx, opt, txn, &o.path).await? {
|
||||
let mut dmp = dmp::new();
|
||||
let mut pch = dmp.patch_from_text(p.value);
|
||||
let (txt, _) = dmp.patch_apply(&mut pch, &v.value);
|
||||
let mut pch = dmp.patch_from_text(p.as_string());
|
||||
let (txt, _) = dmp.patch_apply(&mut pch, v.as_str());
|
||||
let txt = txt.into_iter().collect::<String>();
|
||||
self.set(ctx, opt, txn, &o.path, Value::from(txt)).await?;
|
||||
}
|
||||
|
|
|
@ -479,7 +479,7 @@ impl Value {
|
|||
pub fn is_true(&self) -> bool {
|
||||
match self {
|
||||
Value::True => true,
|
||||
Value::Strand(v) => v.value.to_ascii_lowercase() == "true",
|
||||
Value::Strand(v) => v.to_ascii_lowercase() == "true",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ impl Value {
|
|||
pub fn is_false(&self) -> bool {
|
||||
match self {
|
||||
Value::False => true,
|
||||
Value::Strand(v) => v.value.to_ascii_lowercase() == "false",
|
||||
Value::Strand(v) => v.to_ascii_lowercase() == "false",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ impl Value {
|
|||
Value::Geometry(_) => true,
|
||||
Value::Array(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::Duration(v) => v.value.as_nanos() > 0,
|
||||
Value::Datetime(v) => v.value.timestamp() > 0,
|
||||
|
@ -549,7 +549,7 @@ impl Value {
|
|||
pub fn as_int(self) -> i64 {
|
||||
match self {
|
||||
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::Duration(v) => v.value.as_secs() as i64,
|
||||
Value::Datetime(v) => v.value.timestamp(),
|
||||
|
@ -560,7 +560,7 @@ impl Value {
|
|||
pub fn as_float(self) -> f64 {
|
||||
match self {
|
||||
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::Duration(v) => v.value.as_secs() 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 {
|
||||
match self {
|
||||
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
|
||||
// -----------------------------------
|
||||
|
@ -660,7 +660,7 @@ impl Value {
|
|||
|
||||
pub fn to_idiom(&self) -> Idiom {
|
||||
self.to_strand()
|
||||
.value
|
||||
.as_str()
|
||||
.trim_start_matches('/')
|
||||
.split(&['.', '/'][..])
|
||||
.map(Part::from)
|
||||
|
@ -854,7 +854,7 @@ impl Value {
|
|||
match self {
|
||||
Value::Strand(v) => match other {
|
||||
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),
|
||||
}
|
||||
|
@ -878,8 +878,8 @@ impl Value {
|
|||
match self {
|
||||
Value::Array(v) => v.iter().any(|v| v.equal(other)),
|
||||
Value::Strand(v) => match other {
|
||||
Value::Strand(w) => v.value.contains(w.as_str()),
|
||||
_ => v.value.contains(&other.to_strand().as_str()),
|
||||
Value::Strand(w) => v.contains(w.as_str()),
|
||||
_ => v.contains(&other.to_string().as_str()),
|
||||
},
|
||||
Value::Geometry(v) => match other {
|
||||
Value::Geometry(w) => v.contains(w),
|
||||
|
@ -927,27 +927,21 @@ impl Value {
|
|||
|
||||
pub fn lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(Value::Strand(a), Value::Strand(b)) => {
|
||||
Some(lexical_sort::lexical_cmp(&a.value, &b.value))
|
||||
}
|
||||
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::lexical_cmp(a, b)),
|
||||
_ => self.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn natural_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(Value::Strand(a), Value::Strand(b)) => {
|
||||
Some(lexical_sort::natural_cmp(&a.value, &b.value))
|
||||
}
|
||||
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::natural_cmp(a, b)),
|
||||
_ => self.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn natural_lexical_cmp(&self, other: &Value) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(Value::Strand(a), Value::Strand(b)) => {
|
||||
Some(lexical_sort::natural_lexical_cmp(&a.value, &b.value))
|
||||
}
|
||||
(Value::Strand(a), Value::Strand(b)) => Some(lexical_sort::natural_lexical_cmp(a, b)),
|
||||
_ => self.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
|
@ -1330,6 +1324,24 @@ mod tests {
|
|||
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]
|
||||
fn serialize_deserialize() {
|
||||
let val = Value::parse(
|
||||
|
|
Loading…
Reference in a new issue