1use std::ops::{Deref, DerefMut};
7
8use sqlx::database::Database;
9use sqlx::decode::Decode;
10use sqlx::encode::{Encode, IsNull};
11use sqlx::error::BoxDynError;
12use sqlx::sqlite::{SqliteArgumentValue, SqliteTypeInfo};
13use sqlx::types::Type;
14
15#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
59pub struct Bitcode<T: ?Sized>(pub T);
60
61impl<T> From<T> for Bitcode<T> {
62 fn from(value: T) -> Self {
63 Self(value)
64 }
65}
66
67impl<T> Deref for Bitcode<T> {
68 type Target = T;
69
70 fn deref(&self) -> &Self::Target {
71 &self.0
72 }
73}
74
75impl<T> DerefMut for Bitcode<T> {
76 fn deref_mut(&mut self) -> &mut Self::Target {
77 &mut self.0
78 }
79}
80
81impl<T> AsRef<T> for Bitcode<T> {
82 fn as_ref(&self) -> &T {
83 &self.0
84 }
85}
86
87impl<T> AsMut<T> for Bitcode<T> {
88 fn as_mut(&mut self) -> &mut T {
89 &mut self.0
90 }
91}
92
93impl<T> Bitcode<T>
94where
95 T: bitcode::Encode,
96{
97 pub fn encode_to(&self) -> Vec<u8> {
99 bitcode::encode(&self.0)
100 }
101}
102
103impl<T> Bitcode<T>
104where
105 T: bitcode::DecodeOwned,
106{
107 pub fn decode_from_bytes(bytes: &[u8]) -> Result<Self, bitcode::Error> {
113 let data = bitcode::decode::<T>(bytes)?;
114 Ok(Self(data))
115 }
116}
117
118impl<T> Type<sqlx::Sqlite> for Bitcode<T> {
119 fn type_info() -> SqliteTypeInfo {
120 <&[u8] as Type<sqlx::Sqlite>>::type_info()
121 }
122
123 fn compatible(ty: &SqliteTypeInfo) -> bool {
124 <&[u8] as Type<sqlx::Sqlite>>::compatible(ty)
125 }
126}
127
128impl<T> Encode<'_, sqlx::Sqlite> for Bitcode<T>
129where
130 T: bitcode::Encode,
131{
132 fn encode_by_ref(
133 &self,
134 buf: &mut <sqlx::Sqlite as Database>::ArgumentBuffer<'_>,
135 ) -> Result<IsNull, BoxDynError> {
136 buf.push(SqliteArgumentValue::Blob(std::borrow::Cow::Owned(
137 self.encode_to(),
138 )));
139
140 Ok(IsNull::No)
141 }
142}
143
144impl<'r, T> Decode<'r, sqlx::Sqlite> for Bitcode<T>
145where
146 T: bitcode::DecodeOwned,
147 Vec<u8>: sqlx::Decode<'r, sqlx::Sqlite>,
148{
149 fn decode(value: <sqlx::Sqlite as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
150 let decoded = Vec::<u8>::decode(value)?;
151 let data = Bitcode::<T>::decode_from_bytes(&decoded[..])?;
152
153 Ok(data)
154 }
155}