-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This introduces a Ulid struct which implements sqlx::Type<sqlx::Postgres>, meaning it can be decoding from queries. Support in sqlx for these custom types seems not entirely fleshed out, but with some extra code at query time this works fine.
- Loading branch information
1 parent
781735c
commit 7cbf755
Showing
8 changed files
with
323 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "lockpad-ulid" | ||
version.workspace = true | ||
edition.workspace = true | ||
|
||
[dependencies] | ||
anyhow.workspace = true | ||
rusty_ulid = { version = "2.0.0", features = ["chrono", "rand", "serde"], default-features = false } | ||
sqlx = { version = "0.6.3", features = ["offline", "runtime-tokio-rustls", "postgres", "time", "macros", "uuid"] } | ||
# serde.workspace = true | ||
# serde_json = "1.0.87" | ||
thiserror.workspace = true | ||
tokio.workspace = true | ||
tracing.workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
#[error("todo")] | ||
Todo, | ||
} | ||
|
||
pub type Result<T> = std::result::Result<T, Error>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use sqlx::{encode::IsNull, postgres::PgHasArrayType, Decode, Encode}; | ||
pub mod error; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
pub struct Ulid(rusty_ulid::Ulid); | ||
|
||
impl Ulid { | ||
pub fn generate() -> Self { | ||
Ulid(rusty_ulid::Ulid::generate()) | ||
} | ||
} | ||
|
||
impl From<Ulid> for rusty_ulid::Ulid { | ||
fn from(ulid: Ulid) -> Self { | ||
ulid.0 | ||
} | ||
} | ||
|
||
impl std::str::FromStr for Ulid { | ||
type Err = rusty_ulid::DecodingError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
rusty_ulid::Ulid::from_str(s).map(Ulid) | ||
} | ||
} | ||
|
||
impl std::fmt::Display for Ulid { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl sqlx::Type<sqlx::Postgres> for Ulid { | ||
fn type_info() -> sqlx::postgres::PgTypeInfo { | ||
sqlx::postgres::PgTypeInfo::with_name("ulid") | ||
} | ||
} | ||
|
||
impl PgHasArrayType for Ulid { | ||
fn array_type_info() -> sqlx::postgres::PgTypeInfo { | ||
sqlx::postgres::PgTypeInfo::with_name("_ulid") | ||
} | ||
} | ||
|
||
impl Encode<'_, sqlx::Postgres> for Ulid { | ||
fn encode_by_ref(&self, buf: &mut sqlx::postgres::PgArgumentBuffer) -> IsNull { | ||
let bytes: [u8; 16] = self.0.into(); | ||
buf.extend_from_slice(&bytes); | ||
IsNull::No | ||
} | ||
} | ||
|
||
impl Decode<'_, sqlx::Postgres> for Ulid { | ||
fn decode(value: sqlx::postgres::PgValueRef<'_>) -> Result<Self, sqlx::error::BoxDynError> { | ||
let bytes = value.as_bytes()?; | ||
let ulid = rusty_ulid::Ulid::try_from(bytes)?; | ||
Ok(Ulid(ulid)) | ||
} | ||
} | ||
|
||
impl std::convert::From<Ulid> for sqlx::types::Uuid { | ||
fn from(ulid: Ulid) -> Self { | ||
let bytes: [u8; 16] = ulid.0.into(); | ||
sqlx::types::Uuid::from_bytes(bytes) | ||
} | ||
} |
Oops, something went wrong.