From 10f2911d44302d6e63b849c5dd4f4c8d65fee6e3 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Thu, 5 May 2022 06:01:00 +0100 Subject: [PATCH] Implement SQL Datetime as a newtype tuple struct --- lib/src/fnc/time.rs | 44 +++++++++++++++--------------- lib/src/sql/datetime.rs | 56 ++++++++++++++------------------------ lib/src/sql/duration.rs | 6 ++-- lib/src/sql/value/value.rs | 12 ++++---- 4 files changed, 51 insertions(+), 67 deletions(-) diff --git a/lib/src/fnc/time.rs b/lib/src/fnc/time.rs index c7099f74..d147b42e 100644 --- a/lib/src/fnc/time.rs +++ b/lib/src/fnc/time.rs @@ -12,7 +12,7 @@ pub fn day(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().day().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.day().into()), + Value::Datetime(v) => Ok(v.day().into()), _ => Ok(Value::None), }, } @@ -22,7 +22,7 @@ pub fn floor(_: &Runtime, mut args: Vec) -> Result { match args.remove(0) { Value::Datetime(v) => match args.remove(0) { Value::Duration(w) => match chrono::Duration::from_std(w.value) { - Ok(d) => match v.value.duration_trunc(d) { + Ok(d) => match v.duration_trunc(d) { Ok(v) => Ok(v.into()), _ => Ok(Value::None), }, @@ -38,23 +38,23 @@ pub fn group(_: &Runtime, mut args: Vec) -> Result { match args.remove(0) { Value::Datetime(v) => match args.remove(0) { 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()), + "year" => Ok(Utc.ymd(v.year(), 1, 1).and_hms(0, 0, 0).into()), + "month" => Ok(Utc.ymd(v.year(), v.month(), 1).and_hms(0, 0, 0).into()), "day" => Ok(Utc - .ymd(v.value.year(), v.value.month(), v.value.day()) + .ymd(v.year(), v.month(), v.day()) .and_hms(0, 0, 0) .into()), "hour" => Ok(Utc - .ymd(v.value.year(), v.value.month(), v.value.day()) - .and_hms(v.value.hour(), 0, 0) + .ymd(v.year(), v.month(), v.day()) + .and_hms(v.hour(), 0, 0) .into()), "minute" => Ok(Utc - .ymd(v.value.year(), v.value.month(), v.value.day()) - .and_hms(v.value.hour(), v.value.minute(), 0) + .ymd(v.year(), v.month(), v.day()) + .and_hms(v.hour(), v.minute(), 0) .into()), "second" => Ok(Utc - .ymd(v.value.year(), v.value.month(), v.value.day()) - .and_hms(v.value.hour(), v.value.minute(), v.value.second()) + .ymd(v.year(), v.month(), v.day()) + .and_hms(v.hour(), v.minute(), v.second()) .into()), _ => Err(Error::InvalidArguments { name: String::from("time::group"), @@ -71,7 +71,7 @@ pub fn hour(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().hour().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.hour().into()), + Value::Datetime(v) => Ok(v.hour().into()), _ => Ok(Value::None), }, } @@ -81,7 +81,7 @@ pub fn mins(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().minute().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.minute().into()), + Value::Datetime(v) => Ok(v.minute().into()), _ => Ok(Value::None), }, } @@ -91,7 +91,7 @@ pub fn month(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().day().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.day().into()), + Value::Datetime(v) => Ok(v.day().into()), _ => Ok(Value::None), }, } @@ -101,7 +101,7 @@ pub fn nano(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().timestamp_nanos().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.timestamp_nanos().into()), + Value::Datetime(v) => Ok(v.timestamp_nanos().into()), _ => Ok(Value::None), }, } @@ -115,7 +115,7 @@ pub fn round(_: &Runtime, mut args: Vec) -> Result { match args.remove(0) { Value::Datetime(v) => match args.remove(0) { Value::Duration(w) => match chrono::Duration::from_std(w.value) { - Ok(d) => match v.value.duration_round(d) { + Ok(d) => match v.duration_round(d) { Ok(v) => Ok(v.into()), _ => Ok(Value::None), }, @@ -131,7 +131,7 @@ pub fn secs(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().second().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.second().into()), + Value::Datetime(v) => Ok(v.second().into()), _ => Ok(Value::None), }, } @@ -141,7 +141,7 @@ pub fn unix(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().timestamp().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.timestamp().into()), + Value::Datetime(v) => Ok(v.timestamp().into()), _ => Ok(Value::None), }, } @@ -151,7 +151,7 @@ pub fn wday(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().weekday().number_from_monday().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.weekday().number_from_monday().into()), + Value::Datetime(v) => Ok(v.weekday().number_from_monday().into()), _ => Ok(Value::None), }, } @@ -161,7 +161,7 @@ pub fn week(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().iso_week().week().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.iso_week().week().into()), + Value::Datetime(v) => Ok(v.iso_week().week().into()), _ => Ok(Value::None), }, } @@ -171,7 +171,7 @@ pub fn yday(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().ordinal().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.ordinal().into()), + Value::Datetime(v) => Ok(v.ordinal().into()), _ => Ok(Value::None), }, } @@ -181,7 +181,7 @@ pub fn year(_: &Runtime, mut args: Vec) -> Result { match args.len() { 0 => Ok(Utc::now().year().into()), _ => match args.remove(0) { - Value::Datetime(v) => Ok(v.value.year().into()), + Value::Datetime(v) => Ok(v.year().into()), _ => Ok(Value::None), }, } diff --git a/lib/src/sql/datetime.rs b/lib/src/sql/datetime.rs index c9feddfc..1d229cbb 100644 --- a/lib/src/sql/datetime.rs +++ b/lib/src/sql/datetime.rs @@ -5,37 +5,29 @@ use nom::branch::alt; use nom::character::complete::char; use nom::combinator::map; use nom::sequence::delimited; -use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; use std::fmt; +use std::ops::Deref; use std::str; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Deserialize)] -pub struct Datetime { - pub value: DateTime, -} +pub struct Datetime(pub DateTime); impl Default for Datetime { fn default() -> Self { - Datetime { - value: Utc::now(), - } + Datetime(Utc::now()) } } impl From for Datetime { fn from(v: i64) -> Self { - Datetime { - value: Utc.timestamp(v, 0), - } + Datetime(Utc.timestamp(v, 0)) } } impl From> for Datetime { fn from(v: DateTime) -> Self { - Datetime { - value: v, - } + Datetime(v) } } @@ -48,9 +40,16 @@ impl<'a> From<&'a str> for Datetime { } } +impl Deref for Datetime { + type Target = DateTime; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl fmt::Display for Datetime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "\"{:?}\"", self.value) + write!(f, "\"{:?}\"", self.0) } } @@ -60,11 +59,9 @@ impl Serialize for Datetime { 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("Datetime", 1)?; - val.serialize_field("value", &self.value)?; - val.end() + serializer.serialize_newtype_struct("Datetime", &self.0) } } } @@ -88,12 +85,7 @@ fn date(i: &str) -> IResult<&str, Datetime> { let (i, day) = day(i)?; let d = Utc.ymd(year, mon, day).and_hms(0, 0, 0); - Ok(( - i, - Datetime { - value: d, - }, - )) + Ok((i, Datetime(d))) } fn time(i: &str) -> IResult<&str, Datetime> { @@ -114,15 +106,11 @@ fn time(i: &str) -> IResult<&str, Datetime> { Some(z) => { let d = z.ymd(year, mon, day).and_hms(hour, min, sec); let d = d.with_timezone(&Utc); - Datetime { - value: d, - } + Datetime(d) } None => { let d = Utc.ymd(year, mon, day).and_hms(hour, min, sec); - Datetime { - value: d, - } + Datetime(d) } }; @@ -148,15 +136,11 @@ fn nano(i: &str) -> IResult<&str, Datetime> { Some(z) => { let d = z.ymd(year, mon, day).and_hms_nano(hour, min, sec, nano); let d = d.with_timezone(&Utc); - Datetime { - value: d, - } + Datetime(d) } None => { let d = Utc.ymd(year, mon, day).and_hms_nano(hour, min, sec, nano); - Datetime { - value: d, - } + Datetime(d) } }; diff --git a/lib/src/sql/duration.rs b/lib/src/sql/duration.rs index d5f61d97..57e7341d 100644 --- a/lib/src/sql/duration.rs +++ b/lib/src/sql/duration.rs @@ -74,7 +74,7 @@ impl ops::Add for Duration { type Output = Datetime; fn add(self, other: Datetime) -> Datetime { match chrono::Duration::from_std(self.value) { - Ok(d) => Datetime::from(other.value + d), + Ok(d) => Datetime::from(other.0 + d), Err(_) => Datetime::default(), } } @@ -84,7 +84,7 @@ impl ops::Sub for Duration { type Output = Datetime; fn sub(self, other: Datetime) -> Datetime { match chrono::Duration::from_std(self.value) { - Ok(d) => Datetime::from(other.value - d), + Ok(d) => Datetime::from(other.0 - d), Err(_) => Datetime::default(), } } @@ -94,7 +94,7 @@ impl ops::Div for Duration { type Output = Datetime; fn div(self, other: Datetime) -> Datetime { match chrono::Duration::from_std(self.value) { - Ok(d) => match other.value.duration_trunc(d) { + Ok(d) => match other.duration_trunc(d) { Ok(v) => Datetime::from(v), Err(_) => Datetime::default(), }, diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index a26e205a..8803fcc9 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -503,7 +503,7 @@ impl Value { 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, + Value::Datetime(v) => v.timestamp() > 0, _ => false, } } @@ -552,7 +552,7 @@ impl Value { Value::Strand(v) => v.parse::().unwrap_or(0), Value::Number(v) => v.as_int(), Value::Duration(v) => v.value.as_secs() as i64, - Value::Datetime(v) => v.value.timestamp(), + Value::Datetime(v) => v.timestamp(), _ => 0, } } @@ -563,7 +563,7 @@ impl Value { Value::Strand(v) => v.parse::().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, + Value::Datetime(v) => v.timestamp() as f64, _ => 0.0, } } @@ -574,7 +574,7 @@ impl Value { Value::Number(v) => v.as_decimal(), Value::Strand(v) => BigDecimal::from_str(v.as_str()).unwrap_or_default(), Value::Duration(v) => v.value.as_secs().into(), - Value::Datetime(v) => v.value.timestamp().into(), + Value::Datetime(v) => v.timestamp().into(), _ => BigDecimal::default(), } } @@ -585,7 +585,7 @@ impl Value { Value::Number(v) => v, Value::Strand(v) => Number::from(v.as_str()), Value::Duration(v) => v.value.as_secs().into(), - Value::Datetime(v) => v.value.timestamp().into(), + Value::Datetime(v) => v.timestamp().into(), _ => Number::default(), } } @@ -630,7 +630,7 @@ impl Value { Value::Number(v) => v.clone(), Value::Strand(v) => Number::from(v.as_str()), Value::Duration(v) => v.value.as_secs().into(), - Value::Datetime(v) => v.value.timestamp().into(), + Value::Datetime(v) => v.timestamp().into(), _ => Number::default(), } }