Skip to content

Commit

Permalink
chrono: add support for chronov3
Browse files Browse the repository at this point in the history
  • Loading branch information
muzarski committed Apr 25, 2024
1 parent f995663 commit 7a0d3c9
Show file tree
Hide file tree
Showing 9 changed files with 564 additions and 12 deletions.
68 changes: 59 additions & 9 deletions Cargo.lock.msrv

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

4 changes: 3 additions & 1 deletion scylla-cql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ thiserror = "1.0"
num-bigint-03 = { package = "num-bigint", version = "0.3", optional = true }
num-bigint-04 = { package = "num-bigint", version = "0.4", optional = true }
bigdecimal-04 = { package = "bigdecimal", version = "0.4", optional = true }
chrono-03 = { package = "chrono", version = "0.3", default-features = false, optional = true }
chrono-04 = { package = "chrono", version = "0.4.32", default-features = false, optional = true }
lz4_flex = { version = "0.11.1" }
async-trait = "0.1.57"
Expand All @@ -41,11 +42,12 @@ harness = false
secrecy-08 = ["dep:secrecy-08"]
time-02 = ["dep:time-02"]
time-03 = ["dep:time-03"]
chrono-03 = ["dep:chrono-03"]
chrono-04 = ["dep:chrono-04"]
num-bigint-03 = ["dep:num-bigint-03"]
num-bigint-04 = ["dep:num-bigint-04"]
bigdecimal-04 = ["dep:bigdecimal-04"]
full-serialization = ["chrono-04", "time-02", "time-03", "secrecy-08", "num-bigint-03", "num-bigint-04", "bigdecimal-04"]
full-serialization = ["chrono-03", "chrono-04", "time-02", "time-03", "secrecy-08", "num-bigint-03", "num-bigint-04", "bigdecimal-04"]

[lints.rust]
unreachable_pub = "warn"
124 changes: 124 additions & 0 deletions scylla-cql/src/frame/response/cql_to_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,16 @@ impl FromCqlVal<CqlValue> for bigdecimal_04::BigDecimal {
}
}

#[cfg(feature = "chrono-03")]
impl FromCqlVal<CqlValue> for chrono_03::NaiveDate {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
match cql_val {
CqlValue::Date(cql_date) => cql_date.try_into().map_err(|_| FromCqlValError::BadVal),
_ => Err(FromCqlValError::BadCqlType),
}
}
}

#[cfg(feature = "chrono-04")]
impl FromCqlVal<CqlValue> for chrono_04::NaiveDate {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
Expand Down Expand Up @@ -205,6 +215,16 @@ impl FromCqlVal<CqlValue> for time_03::Date {
}
}

#[cfg(feature = "chrono-03")]
impl FromCqlVal<CqlValue> for chrono_03::NaiveTime {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
match cql_val {
CqlValue::Time(cql_time) => cql_time.try_into().map_err(|_| FromCqlValError::BadVal),
_ => Err(FromCqlValError::BadCqlType),
}
}
}

#[cfg(feature = "chrono-04")]
impl FromCqlVal<CqlValue> for chrono_04::NaiveTime {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
Expand Down Expand Up @@ -235,6 +255,17 @@ impl FromCqlVal<CqlValue> for time_03::Time {
}
}

#[cfg(feature = "chrono-03")]
impl FromCqlVal<CqlValue> for chrono_03::DateTime<chrono_03::UTC> {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
cql_val
.as_cql_timestamp()
.ok_or(FromCqlValError::BadCqlType)?
.try_into()
.map_err(|_| FromCqlValError::BadVal)
}
}

#[cfg(feature = "chrono-04")]
impl FromCqlVal<CqlValue> for chrono_04::DateTime<chrono_04::Utc> {
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
Expand Down Expand Up @@ -554,6 +585,36 @@ mod tests {
assert_eq!(Ok(counter), Counter::from_cql(CqlValue::Counter(counter)));
}

#[cfg(feature = "chrono-03")]
#[test]
fn naive_date_03_from_cql() {
use chrono_03::NaiveDate;

let unix_epoch: CqlValue = CqlValue::Date(CqlDate(2_u32.pow(31)));
assert_eq!(
Ok(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()),
NaiveDate::from_cql(unix_epoch)
);

let before_epoch: CqlValue = CqlValue::Date(CqlDate(2_u32.pow(31) - 30));
assert_eq!(
Ok(NaiveDate::from_ymd_opt(1969, 12, 2).unwrap()),
NaiveDate::from_cql(before_epoch)
);

let after_epoch: CqlValue = CqlValue::Date(CqlDate(2_u32.pow(31) + 30));
assert_eq!(
Ok(NaiveDate::from_ymd_opt(1970, 1, 31).unwrap()),
NaiveDate::from_cql(after_epoch)
);

let min_date: CqlValue = CqlValue::Date(CqlDate(0));
assert!(NaiveDate::from_cql(min_date).is_err());

let max_date: CqlValue = CqlValue::Date(CqlDate(u32::MAX));
assert!(NaiveDate::from_cql(max_date).is_err());
}

#[cfg(feature = "chrono-04")]
#[test]
fn naive_date_04_from_cql() {
Expand Down Expand Up @@ -662,6 +723,50 @@ mod tests {
assert_eq!(time_ns, CqlTime::from_cql(cql_value).unwrap().0);
}

#[cfg(feature = "chrono-03")]
#[test]
fn naive_time_03_from_cql() {
use chrono_03::NaiveTime;

// Midnight
let midnight = CqlValue::Time(CqlTime(0));
assert_eq!(
Ok(NaiveTime::from_hms(0, 0, 0)),
NaiveTime::from_cql(midnight)
);

// 7:15:21.123456789
let morning = CqlValue::Time(CqlTime(
(7 * 3600 + 15 * 60 + 21) * 1_000_000_000 + 123_456_789,
));
assert_eq!(
Ok(NaiveTime::from_hms_nano_opt(7, 15, 21, 123_456_789).unwrap()),
NaiveTime::from_cql(morning)
);

// 23:59:59.999999999
let late_night = CqlValue::Time(CqlTime(
(23 * 3600 + 59 * 60 + 59) * 1_000_000_000 + 999_999_999,
));
assert_eq!(
Ok(NaiveTime::from_hms_nano_opt(23, 59, 59, 999_999_999).unwrap()),
NaiveTime::from_cql(late_night)
);

// Bad values. Since value is out of `chrono_04::NaiveTime` range, it should return `BadVal` error
let bad_time1 = CqlValue::Time(CqlTime(-1));
assert_eq!(Err(FromCqlValError::BadVal), NaiveTime::from_cql(bad_time1));
let bad_time2 = CqlValue::Time(CqlTime(i64::MAX));
assert_eq!(Err(FromCqlValError::BadVal), NaiveTime::from_cql(bad_time2));

// Different CQL type. Since value can't be casted, it should return `BadCqlType` error
let bad_type = CqlValue::Double(0.5);
assert_eq!(
Err(FromCqlValError::BadCqlType),
NaiveTime::from_cql(bad_type)
);
}

#[cfg(feature = "chrono-04")]
#[test]
fn naive_time_04_from_cql() {
Expand Down Expand Up @@ -762,6 +867,25 @@ mod tests {
);
}

#[cfg(feature = "chrono-03")]
#[test]
fn datetime_03_from_cql() {
use chrono_03::{DateTime, NaiveDate, UTC};
let naivedatetime_utc = NaiveDate::from_ymd_opt(2022, 12, 31)
.unwrap()
.and_hms_opt(2, 0, 0)
.unwrap();
let datetime_utc = DateTime::<UTC>::from_utc(naivedatetime_utc, UTC);

assert_eq!(
datetime_utc,
DateTime::<UTC>::from_cql(CqlValue::Timestamp(CqlTimestamp(
datetime_utc.timestamp() * 1000 + datetime_utc.timestamp_subsec_millis() as i64
)))
.unwrap()
);
}

#[cfg(feature = "chrono-04")]
#[test]
fn datetime_04_from_cql() {
Expand Down
Loading

0 comments on commit 7a0d3c9

Please sign in to comment.