From 3831e5a42ab4e21f116537c5251582245de37f0b Mon Sep 17 00:00:00 2001 From: rtkay123 Date: Fri, 25 Jul 2025 18:37:28 +0200 Subject: feat(lib): auth rpc --- lib/sellershut-core/src/auth.rs | 3 + lib/sellershut-core/src/google.rs | 7 ++ lib/sellershut-core/src/google/helpers.rs | 125 ++++++++++++++++++++++++++++++ lib/sellershut-core/src/lib.rs | 13 ++++ 4 files changed, 148 insertions(+) create mode 100644 lib/sellershut-core/src/auth.rs create mode 100644 lib/sellershut-core/src/google.rs create mode 100644 lib/sellershut-core/src/google/helpers.rs create mode 100644 lib/sellershut-core/src/lib.rs (limited to 'lib/sellershut-core/src') diff --git a/lib/sellershut-core/src/auth.rs b/lib/sellershut-core/src/auth.rs new file mode 100644 index 0000000..d555aab --- /dev/null +++ b/lib/sellershut-core/src/auth.rs @@ -0,0 +1,3 @@ +tonic::include_proto!("auth"); +/// Auth file descriptor +pub const AUTH_FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("auth_descriptor"); diff --git a/lib/sellershut-core/src/google.rs b/lib/sellershut-core/src/google.rs new file mode 100644 index 0000000..b28aee0 --- /dev/null +++ b/lib/sellershut-core/src/google.rs @@ -0,0 +1,7 @@ +/// Well known types +pub mod protobuf { + include!(concat!(env!("OUT_DIR"), "/google.protobuf.rs")); +} + +#[cfg(feature = "time")] +mod helpers; diff --git a/lib/sellershut-core/src/google/helpers.rs b/lib/sellershut-core/src/google/helpers.rs new file mode 100644 index 0000000..2d75655 --- /dev/null +++ b/lib/sellershut-core/src/google/helpers.rs @@ -0,0 +1,125 @@ +use crate::google::protobuf::Timestamp; + +#[derive(serde::Serialize, serde::Deserialize)] +#[serde(untagged)] +/// Date utility +#[derive(Clone, Debug)] +pub enum DateItem { + /// string + String(String), + /// ts + Timestamp { seconds: i64, nanos: i32 }, +} + +impl TryFrom for Timestamp { + type Error = time::Error; + + fn try_from(value: DateItem) -> Result { + match value { + DateItem::String(ref string) => ::from_str(string), + DateItem::Timestamp { seconds, nanos } => Ok(Self { seconds, nanos }), + } + } +} + +impl From for Timestamp { + fn from(dt: time::OffsetDateTime) -> Self { + Timestamp { + seconds: dt.unix_timestamp(), + nanos: dt.nanosecond() as i32, + } + } +} + +impl From for String { + fn from(value: Timestamp) -> Self { + let odt = time::OffsetDateTime::try_from(value).expect("invalid date"); + odt.format(&time::format_description::well_known::Rfc3339) + .expect("format is not rfc3339") + } +} + +impl std::str::FromStr for Timestamp { + type Err = time::Error; + + fn from_str(s: &str) -> Result { + let timestamp = + time::OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)?; + + Ok(Timestamp::from(timestamp)) + } +} + +impl TryFrom for Timestamp { + type Error = time::Error; + + fn try_from(value: String) -> Result { + ::from_str(&value) + } +} + +impl TryFrom for time::OffsetDateTime { + type Error = time::Error; + + fn try_from(value: Timestamp) -> Result { + let dt = time::OffsetDateTime::from_unix_timestamp(value.seconds)?; + + Ok(dt.replace_nanosecond(value.nanos as u32)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use time::{Duration, OffsetDateTime}; + + #[test] + fn test_offsetdatetime_to_timestamp() { + let now = OffsetDateTime::now_utc(); + let timestamp: Timestamp = now.into(); + + assert_eq!(timestamp.seconds, now.unix_timestamp()); + assert_eq!(timestamp.nanos, now.nanosecond() as i32); + } + + #[test] + fn test_timestamp_to_offsetdatetime() { + let now = OffsetDateTime::now_utc(); + let timestamp: Timestamp = now.into(); + let dt: OffsetDateTime = timestamp.try_into().unwrap(); + + assert_eq!(dt, now); + } + + #[test] + fn test_timestamp_to_offsetdatetime_with_nanos() { + let now = OffsetDateTime::now_utc(); + let nanos = 123456789; + let dt = now + Duration::nanoseconds(nanos); + let timestamp: Timestamp = dt.into(); + let dt_from_timestamp: OffsetDateTime = timestamp.try_into().unwrap(); + + assert_eq!(dt_from_timestamp, dt); + } + + #[test] + fn test_timestamp_to_offsetdatetime_with_negative_nanos() { + let now = OffsetDateTime::now_utc(); + let nanos = -123456789; + let dt = now + Duration::nanoseconds(nanos); + let timestamp: Timestamp = dt.into(); + let dt_from_timestamp: OffsetDateTime = timestamp.try_into().unwrap(); + + assert_eq!(dt_from_timestamp, dt); + } + + #[test] + fn test_timestamp_to_offsetdatetime_invalid_seconds() { + let timestamp = Timestamp { + seconds: i64::MIN, + nanos: 0, + }; + let result: Result = timestamp.try_into(); + assert!(result.is_err()); + } +} diff --git a/lib/sellershut-core/src/lib.rs b/lib/sellershut-core/src/lib.rs new file mode 100644 index 0000000..ee2ed9b --- /dev/null +++ b/lib/sellershut-core/src/lib.rs @@ -0,0 +1,13 @@ +//! Core +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn( + missing_docs, + rustdoc::broken_intra_doc_links, + missing_debug_implementations +)] + +/// Protobuf types +#[cfg(feature = "auth")] +pub mod google; + +pub mod auth; -- cgit v1.2.3