diesel_chrono_duration/
lib.rs

1//! # diesel-chrono-duration
2//!
3//! This crate implements storage functionality for the `chrono::Duration` type.
4//! It could be included into the `diesel` itself but its policy does not allow that.
5//!
6//! ## Usage
7//!
8//! Just use the [`ChronoDurationProxy`](https://docs.rs/diesel-chrono-duration) type instead of vanilla [`chrono::Duration`](https://docs.rs/chrono/0.4.6/chrono/struct.Duration.html).
9
10#![warn(missing_docs)]
11
12use diesel::backend::Backend;
13use diesel::deserialize::{self, FromSql};
14use diesel::query_builder::bind_collector::RawBytesBindCollector;
15use diesel::serialize::{self, Output, ToSql};
16use diesel::sql_types::BigInt;
17use diesel::{AsExpression, FromSqlRow};
18
19/// A proxy type for which the diesel traits are implemented. Use this type whenever
20/// you want to operate with `chrono::Duration`.
21#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromSqlRow, AsExpression)]
22#[diesel(sql_type = BigInt)]
23pub struct ChronoDurationProxy(pub chrono::Duration);
24
25impl From<chrono::Duration> for ChronoDurationProxy {
26    fn from(duration: chrono::Duration) -> ChronoDurationProxy {
27        ChronoDurationProxy(duration)
28    }
29}
30
31impl AsRef<chrono::Duration> for ChronoDurationProxy {
32    fn as_ref(&self) -> &chrono::Duration {
33        &self.0
34    }
35}
36
37impl std::ops::Deref for ChronoDurationProxy {
38    type Target = chrono::Duration;
39
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl<DB> ToSql<BigInt, DB> for ChronoDurationProxy
46where
47    i64: ToSql<BigInt, DB>,
48    for<'c> DB: Backend + Backend<BindCollector<'c> = RawBytesBindCollector<DB>>,
49{
50    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
51        if let Some(num_nanoseconds) = self.0.num_nanoseconds() {
52            //<i64 as ToSql<BigInt, DB>>::to_sql(&num_nanoseconds, &mut out.reborrow())
53            num_nanoseconds.to_sql(&mut out.reborrow())
54        } else {
55            Err(format!("{:?} as nanoseconds is too large to fit in an i64", self).into())
56        }
57    }
58}
59
60impl<DB> FromSql<BigInt, DB> for ChronoDurationProxy
61where
62    i64: FromSql<BigInt, DB>,
63    DB: Backend,
64{
65    fn from_sql(value: DB::RawValue<'_>) -> deserialize::Result<Self> {
66        let i64_value = <i64 as FromSql<BigInt, DB>>::from_sql(value)?;
67        Ok(chrono::Duration::nanoseconds(i64_value).into())
68    }
69}