Skip to main content

sqlx_prost/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3#![doc = include_str!("../README.md")]
4
5use core::ops::{Deref, DerefMut};
6
7use prost::Message;
8use sqlx::decode::Decode;
9use sqlx::encode::{Encode, IsNull};
10use sqlx::error::BoxDynError;
11use sqlx::{Database, Type};
12
13/// Wrapper for Protobuf messages to be used with sqlx.
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct SqlxProto<T>(pub T)
16where
17    T: Message;
18
19impl<T> Default for SqlxProto<T>
20where
21    T: Message + Default,
22{
23    #[inline]
24    fn default() -> Self {
25        Self(T::default())
26    }
27}
28
29impl<T> SqlxProto<T>
30where
31    T: Message,
32{
33    /// Get inner value
34    #[inline]
35    pub fn into_inner(self) -> T {
36        self.0
37    }
38}
39
40impl<T> From<T> for SqlxProto<T>
41where
42    T: Message,
43{
44    #[inline]
45    fn from(value: T) -> SqlxProto<T> {
46        Self(value)
47    }
48}
49
50impl<T> AsRef<T> for SqlxProto<T>
51where
52    T: Message,
53{
54    #[inline]
55    fn as_ref(&self) -> &T {
56        &self.0
57    }
58}
59
60impl<T> AsMut<T> for SqlxProto<T>
61where
62    T: Message,
63{
64    #[inline]
65    fn as_mut(&mut self) -> &mut T {
66        &mut self.0
67    }
68}
69
70impl<T> Deref for SqlxProto<T>
71where
72    T: Message,
73{
74    type Target = T;
75
76    #[inline]
77    fn deref(&self) -> &Self::Target {
78        &self.0
79    }
80}
81
82impl<T> DerefMut for SqlxProto<T>
83where
84    T: Message,
85{
86    #[inline]
87    fn deref_mut(&mut self) -> &mut Self::Target {
88        &mut self.0
89    }
90}
91
92impl<T, DB> Type<DB> for SqlxProto<T>
93where
94    T: Message,
95    DB: Database,
96    Vec<u8>: Type<DB>,
97{
98    fn type_info() -> DB::TypeInfo {
99        <Vec<u8> as Type<DB>>::type_info()
100    }
101}
102
103impl<'a, T, DB> Encode<'a, DB> for SqlxProto<T>
104where
105    T: Message,
106    DB: Database,
107    Vec<u8>: Encode<'a, DB>,
108{
109    fn encode_by_ref(
110        &self,
111        buf: &mut <DB as Database>::ArgumentBuffer<'a>,
112    ) -> Result<IsNull, BoxDynError> {
113        let bytes = self.0.encode_to_vec();
114        <Vec<u8> as Encode<DB>>::encode_by_ref(&bytes, buf)
115    }
116}
117
118impl<'r, T, DB> Decode<'r, DB> for SqlxProto<T>
119where
120    T: Message + Default,
121    DB: Database,
122    Vec<u8>: Decode<'r, DB>,
123{
124    fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
125        let bytes: Vec<u8> = <Vec<u8> as Decode<DB>>::decode(value)?;
126        Ok(Self(T::decode(bytes.as_slice())?))
127    }
128}