Skip to content

Commit 28e270a

Browse files
committed
Made Choice generic over postgres type name
1 parent 7a1c953 commit 28e270a

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

src/choice.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
//! Wrapper around string which is decodable as an enum
22
3+
use std::marker::PhantomData;
4+
35
/// Wrapper around string which is decodable as an enum
4-
pub struct Choice(pub String);
6+
///
7+
/// Postgres creates a new type for enums with a unique name.
8+
/// Therefore, `Choice` is generic over a ZST which implements [`ChoiceName`] to provide the postgres name.
9+
///
10+
/// If the generic is not provided, `Choice` won't be usable with postgres
11+
pub struct Choice<N = ()>(pub String, pub PhantomData<N>);
12+
13+
/// Trait to associate a postgres type name with [`Choice`]
14+
pub trait ChoiceName {
15+
/// The sql name to use for postgres
16+
const NAME: &'static str;
17+
}
518

619
#[cfg(feature = "sqlx")]
720
const _: () = {
@@ -12,53 +25,56 @@ const _: () = {
1225
#[cfg(feature = "postgres")]
1326
const _: () = {
1427
use sqlx::Postgres;
15-
impl Type<Postgres> for Choice {
28+
impl<N: ChoiceName> Type<Postgres> for Choice<N> {
1629
fn type_info() -> <Postgres as Database>::TypeInfo {
17-
<str as Type<Postgres>>::type_info()
30+
sqlx::postgres::PgTypeInfo::with_name(N::NAME)
1831
}
1932
fn compatible(ty: &<Postgres as Database>::TypeInfo) -> bool {
20-
<str as Type<Postgres>>::compatible(ty)
33+
*ty == sqlx::postgres::PgTypeInfo::with_name(N::NAME)
34+
|| <str as Type<Postgres>>::compatible(ty)
2135
}
2236
}
23-
impl<'r> Decode<'r, Postgres> for Choice {
37+
impl<'r, N: ChoiceName> Decode<'r, Postgres> for Choice<N> {
2438
fn decode(value: <Postgres as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
25-
<String as Decode<'r, Postgres>>::decode(value).map(Self)
39+
<String as Decode<'r, Postgres>>::decode(value)
40+
.map(|string| Self(string, PhantomData))
2641
}
2742
}
2843
};
2944

3045
#[cfg(feature = "mysql")]
3146
const _: () = {
3247
use sqlx::MySql;
33-
impl Type<MySql> for Choice {
48+
impl<N> Type<MySql> for Choice<N> {
3449
fn type_info() -> <MySql as Database>::TypeInfo {
3550
<str as Type<MySql>>::type_info()
3651
}
3752
fn compatible(ty: &<MySql as Database>::TypeInfo) -> bool {
3853
<str as Type<MySql>>::compatible(ty)
3954
}
4055
}
41-
impl<'r> Decode<'r, MySql> for Choice {
56+
impl<'r, N> Decode<'r, MySql> for Choice<N> {
4257
fn decode(value: <MySql as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
43-
<String as Decode<'r, MySql>>::decode(value).map(Self)
58+
<String as Decode<'r, MySql>>::decode(value).map(|string| Self(string, PhantomData))
4459
}
4560
}
4661
};
4762

4863
#[cfg(feature = "sqlite")]
4964
const _: () = {
5065
use sqlx::Sqlite;
51-
impl Type<Sqlite> for Choice {
66+
impl<N> Type<Sqlite> for Choice<N> {
5267
fn type_info() -> <Sqlite as Database>::TypeInfo {
5368
<str as Type<Sqlite>>::type_info()
5469
}
5570
fn compatible(ty: &<Sqlite as Database>::TypeInfo) -> bool {
5671
<str as Type<Sqlite>>::compatible(ty)
5772
}
5873
}
59-
impl<'r> Decode<'r, Sqlite> for Choice {
74+
impl<'r, N> Decode<'r, Sqlite> for Choice<N> {
6075
fn decode(value: <Sqlite as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
61-
<String as Decode<'r, Sqlite>>::decode(value).map(Self)
76+
<String as Decode<'r, Sqlite>>::decode(value)
77+
.map(|string| Self(string, PhantomData))
6278
}
6379
}
6480
};

0 commit comments

Comments
 (0)