1use std::ops::{Deref, DerefMut};
2
3#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
6#[serde(transparent)]
7pub struct Json<T>(pub T);
8
9impl<T> Deref for Json<T> {
10 type Target = T;
11
12 fn deref(&self) -> &Self::Target {
13 &self.0
14 }
15}
16
17impl<T> DerefMut for Json<T> {
18 fn deref_mut(&mut self) -> &mut Self::Target {
19 &mut self.0
20 }
21}
22
23#[cfg(not(any(
24 feature = "strict-postgres",
25 feature = "strict-mysql",
26 feature = "strict-sqlite"
27)))]
28impl<'r, T: serde::de::DeserializeOwned> sqlx::Decode<'r, sqlx::Any> for Json<T> {
29 fn decode(
30 value: sqlx::any::AnyValueRef<'r>,
31 ) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
32 let text = <String as sqlx::Decode<sqlx::Any>>::decode(value)?;
33 let parsed: T = serde_json::from_str(&text)?;
34 Ok(Json(parsed))
35 }
36}
37
38#[cfg(not(any(
39 feature = "strict-postgres",
40 feature = "strict-mysql",
41 feature = "strict-sqlite"
42)))]
43impl<'q, T: serde::Serialize> sqlx::Encode<'q, sqlx::Any> for Json<T> {
44 fn encode_by_ref(
45 &self,
46 buf: &mut <sqlx::Any as sqlx::database::Database>::ArgumentBuffer,
47 ) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync>> {
48 let stringified = serde_json::to_string(&self.0)?;
49 <String as sqlx::Encode<sqlx::Any>>::encode(stringified, buf)
50 }
51}
52
53#[cfg(not(any(
54 feature = "strict-postgres",
55 feature = "strict-mysql",
56 feature = "strict-sqlite"
57)))]
58impl<T> sqlx::Type<sqlx::Any> for Json<T> {
59 fn type_info() -> sqlx::any::AnyTypeInfo {
60 <String as sqlx::Type<sqlx::Any>>::type_info()
61 }
62}
63
64#[cfg(any(
65 feature = "strict-postgres",
66 feature = "strict-mysql",
67 feature = "strict-sqlite"
68))]
69impl<'r, T: serde::de::DeserializeOwned> sqlx::Decode<'r, crate::database::RullstDatabase>
70 for Json<T>
71{
72 fn decode(
73 value: <crate::database::RullstDatabase as sqlx::database::Database>::ValueRef<'r>,
74 ) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
75 let text = <String as sqlx::Decode<crate::database::RullstDatabase>>::decode(value)?;
76 let parsed: T = serde_json::from_str(&text)?;
77 Ok(Json(parsed))
78 }
79}
80
81#[cfg(any(
82 feature = "strict-postgres",
83 feature = "strict-mysql",
84 feature = "strict-sqlite"
85))]
86impl<'q, T: serde::Serialize> sqlx::Encode<'q, crate::database::RullstDatabase> for Json<T> {
87 fn encode_by_ref(
88 &self,
89 buf: &mut <crate::database::RullstDatabase as sqlx::database::Database>::ArgumentBuffer,
90 ) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync>> {
91 let stringified = serde_json::to_string(&self.0)?;
92 <String as sqlx::Encode<crate::database::RullstDatabase>>::encode(stringified, buf)
93 }
94}
95
96#[cfg(any(
97 feature = "strict-postgres",
98 feature = "strict-mysql",
99 feature = "strict-sqlite"
100))]
101impl<T> sqlx::Type<crate::database::RullstDatabase> for Json<T> {
102 fn type_info() -> <crate::database::RullstDatabase as sqlx::database::Database>::TypeInfo {
103 <String as sqlx::Type<crate::database::RullstDatabase>>::type_info()
104 }
105}