diff --git a/Cargo.lock b/Cargo.lock index 1477124..5c91b8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,8 +399,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1297,6 +1299,7 @@ dependencies = [ "rand", "serde", "uuid-macro-internal", + "wasm-bindgen", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5514ccb..51db300 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.88" uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } format_num = "0.1.0" -sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ] } -bincode = "1.3.3" \ No newline at end of file +sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ], optional = true } +bincode = "1.3.3" + +[features] +sqlx = ["dep:sqlx"] +wasm = ["uuid/js"] \ No newline at end of file diff --git a/src/domain/contact_info/mod.rs b/src/domain/contact_info/mod.rs index 700fcb0..8a73165 100644 --- a/src/domain/contact_info/mod.rs +++ b/src/domain/contact_info/mod.rs @@ -1,8 +1,6 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; - - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ContactInformation { #[serde(rename = "agentId")] diff --git a/src/domain/property/impls.rs b/src/domain/property/impls.rs new file mode 100644 index 0000000..f507d6a --- /dev/null +++ b/src/domain/property/impls.rs @@ -0,0 +1,30 @@ +use sqlx::{Postgres, postgres::{PgValueRef, PgTypeInfo, PgArgumentBuffer}, error::BoxDynError, encode::IsNull}; + +use super::ListingState; + +impl sqlx::Encode<'_, Postgres> for ListingState { + fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { + let encoded_value = bincode::serialize(self).unwrap(); + as sqlx::Encode>::encode(encoded_value, buf) + } +} + +impl sqlx::Decode<'_, Postgres> for ListingState { + fn decode(value: PgValueRef<'_>) -> Result { + let column = value.as_bytes()?; + match bincode::deserialize(column) { + Ok(listing_state) => Ok(listing_state), + Err(error) => Err(error), + } + } +} + +impl sqlx::Type for ListingState { + fn type_info() -> PgTypeInfo { + PgTypeInfo::with_name("bytea") + } + + fn compatible(ty: &::TypeInfo) -> bool { + *ty == Self::type_info() + } +} diff --git a/src/domain/property/mod.rs b/src/domain/property/mod.rs index 061708c..ea5146f 100644 --- a/src/domain/property/mod.rs +++ b/src/domain/property/mod.rs @@ -1,6 +1,8 @@ +#[cfg(feature = "sqlx")] +pub mod impls; + use chrono::{DateTime, Utc}; use serde::{Serialize, Deserialize}; -use sqlx::{Postgres, postgres::{PgValueRef, PgTypeInfo, PgArgumentBuffer}, error::BoxDynError, encode::IsNull}; use uuid::Uuid; @@ -40,32 +42,4 @@ pub enum ListingState { Sold, Listed, Deleted, -} - - -impl sqlx::Encode<'_, Postgres> for ListingState { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = bincode::serialize(self).unwrap(); - as sqlx::Encode>::encode(encoded_value, buf) - } -} - -impl sqlx::Decode<'_, Postgres> for ListingState { - fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_bytes()?; - match bincode::deserialize(column) { - Ok(listing_state) => Ok(listing_state), - Err(error) => Err(error), - } - } -} - -impl sqlx::Type for ListingState { - fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("bytea") - } - - fn compatible(ty: &::TypeInfo) -> bool { - *ty == Self::type_info() - } -} +} \ No newline at end of file diff --git a/src/domain/property_details/impls.rs b/src/domain/property_details/impls.rs new file mode 100644 index 0000000..be8f323 --- /dev/null +++ b/src/domain/property_details/impls.rs @@ -0,0 +1,69 @@ +use std::str::FromStr; +use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError}; + +use crate::domain::error::InnerError; + +use super::{Photos, ListingType}; + +impl sqlx::Encode<'_, Postgres> for Photos { + fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { + let encoded_value = bincode::serialize(self).unwrap(); + as sqlx::Encode>::encode(encoded_value, buf) + } +} + +impl sqlx::Decode<'_, Postgres> for Photos { + fn decode(value: PgValueRef<'_>) -> Result { + let column = value.as_bytes()?; + match bincode::deserialize(column) { + Ok(listing_state) => Ok(listing_state), + Err(error) => Err(error), + } + } +} + +impl sqlx::Type for Photos { + fn type_info() -> PgTypeInfo { + PgTypeInfo::with_name("bytea") + } + + fn compatible(ty: &::TypeInfo) -> bool { + *ty == Self::type_info() + } +} + + +impl sqlx::Encode<'_, Postgres> for ListingType { + fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { + let encoded_value = self.to_string(); + <&str as sqlx::Encode>::encode(encoded_value.as_str(), buf) + } +} + +impl sqlx::Decode<'_, Postgres> for ListingType { + fn decode(value: PgValueRef<'_>) -> Result { + let column = value.as_str()?; + let col_split = column.split(" ").collect::>(); + match *col_split.first().ok_or(Box::new(InnerError::ParsingFromDb))? { + "rent" => Ok(Self::Rent(f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?)), + "sale" => Ok(Self::Sale(f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?)), + "both" => Ok(Self::Both( + f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?, + f64::from_str(*col_split.get(2).ok_or(Box::new(InnerError::ParsingFromDb))?)?, + )), + _ => { + Err(Box::new(InnerError::ParsingFromDb)) + } + } + } +} + +impl sqlx::Type for ListingType { + fn type_info() -> PgTypeInfo { + PgTypeInfo::with_name("VARCHAR") + } + + fn compatible(ty: &::TypeInfo) -> bool { + *ty == Self::type_info() + } +} \ No newline at end of file diff --git a/src/domain/property_details/mod.rs b/src/domain/property_details/mod.rs index ab72252..cb7f78c 100644 --- a/src/domain/property_details/mod.rs +++ b/src/domain/property_details/mod.rs @@ -1,11 +1,12 @@ +#[cfg(feature = "sqlx")] +pub mod impls; + use std::fmt::Display; use serde::{Serialize, Deserialize}; -use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError}; use uuid::Uuid; -use super::error::InnerError; -use std::str::FromStr; + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Default)] pub struct PropertyDetails { @@ -45,69 +46,4 @@ impl Display for ListingType { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Default)] pub struct Photos { pub photos: Vec -} - -// Database implementations - -impl sqlx::Encode<'_, Postgres> for Photos { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = bincode::serialize(self).unwrap(); - as sqlx::Encode>::encode(encoded_value, buf) - } -} - -impl sqlx::Decode<'_, Postgres> for Photos { - fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_bytes()?; - match bincode::deserialize(column) { - Ok(listing_state) => Ok(listing_state), - Err(error) => Err(error), - } - } -} - -impl sqlx::Type for Photos { - fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("bytea") - } - - fn compatible(ty: &::TypeInfo) -> bool { - *ty == Self::type_info() - } -} - - -impl sqlx::Encode<'_, Postgres> for ListingType { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = self.to_string(); - <&str as sqlx::Encode>::encode(encoded_value.as_str(), buf) - } -} - -impl sqlx::Decode<'_, Postgres> for ListingType { - fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_str()?; - let col_split = column.split(" ").collect::>(); - match *col_split.first().ok_or(Box::new(InnerError::ParsingFromDb))? { - "rent" => Ok(Self::Rent(f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?)), - "sale" => Ok(Self::Sale(f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?)), - "both" => Ok(Self::Both( - f64::from_str(*col_split.get(1).ok_or(Box::new(InnerError::ParsingFromDb))?)?, - f64::from_str(*col_split.get(2).ok_or(Box::new(InnerError::ParsingFromDb))?)?, - )), - _ => { - Err(Box::new(InnerError::ParsingFromDb)) - } - } - } -} - -impl sqlx::Type for ListingType { - fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("VARCHAR") - } - - fn compatible(ty: &::TypeInfo) -> bool { - *ty == Self::type_info() - } } \ No newline at end of file