Skip to main content

uts_sql/
alloy.rs

1use crate::TextWrapper;
2use alloy_primitives::{Address, FixedBytes, Uint, hex};
3use sqlx::{
4    Encode, Sqlite, Type,
5    encode::IsNull,
6    error::BoxDynError,
7    sqlite::{SqliteArgumentValue, SqliteTypeInfo},
8};
9
10impl<const N: usize> Type<Sqlite> for TextWrapper<FixedBytes<N>> {
11    fn type_info() -> SqliteTypeInfo {
12        <String as Type<Sqlite>>::type_info()
13    }
14
15    fn compatible(ty: &SqliteTypeInfo) -> bool {
16        <String as Type<Sqlite>>::compatible(ty)
17    }
18}
19
20impl<const N: usize> Encode<'_, Sqlite> for TextWrapper<FixedBytes<N>> {
21    fn encode_by_ref(
22        &self,
23        args: &mut Vec<SqliteArgumentValue<'_>>,
24    ) -> Result<IsNull, BoxDynError> {
25        let s = hex::encode(self.0.as_slice());
26        args.push(SqliteArgumentValue::Text(s.into()));
27        Ok(IsNull::No)
28    }
29}
30
31impl<'r, const N: usize> ::sqlx::Decode<'r, Sqlite> for TextWrapper<FixedBytes<N>> {
32    fn decode(value: ::sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, BoxDynError> {
33        let text = <&str as ::sqlx::Decode<Sqlite>>::decode(value)?;
34        let bytes = hex::decode(text)?;
35        if bytes.len() != N {
36            return Err(format!("expected {N} bytes but got {}", bytes.len()).into());
37        }
38        let mut ret = [0u8; N];
39        ret.copy_from_slice(&bytes);
40        Ok(TextWrapper(ret.into()))
41    }
42}
43
44impl<const BITS: usize, const LIMBS: usize> Type<Sqlite> for TextWrapper<Uint<BITS, LIMBS>> {
45    fn type_info() -> SqliteTypeInfo {
46        <String as Type<Sqlite>>::type_info()
47    }
48
49    fn compatible(ty: &SqliteTypeInfo) -> bool {
50        <String as Type<Sqlite>>::compatible(ty)
51    }
52}
53
54impl<const BITS: usize, const LIMBS: usize> Encode<'_, Sqlite> for TextWrapper<Uint<BITS, LIMBS>> {
55    fn encode_by_ref(
56        &self,
57        args: &mut Vec<SqliteArgumentValue<'_>>,
58    ) -> Result<IsNull, BoxDynError> {
59        let s = self.0.to_string();
60        args.push(SqliteArgumentValue::Text(s.into()));
61        Ok(IsNull::No)
62    }
63}
64
65impl<'r, const BITS: usize, const LIMBS: usize> ::sqlx::Decode<'r, Sqlite>
66    for TextWrapper<Uint<BITS, LIMBS>>
67{
68    fn decode(value: ::sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, BoxDynError> {
69        let text = <&str as ::sqlx::Decode<Sqlite>>::decode(value)?;
70        let uint = text.parse::<Uint<BITS, LIMBS>>()?;
71        Ok(TextWrapper(uint))
72    }
73}
74
75impl Type<Sqlite> for TextWrapper<Address> {
76    fn type_info() -> SqliteTypeInfo {
77        <String as Type<Sqlite>>::type_info()
78    }
79
80    fn compatible(ty: &SqliteTypeInfo) -> bool {
81        <String as Type<Sqlite>>::compatible(ty)
82    }
83}
84
85impl Encode<'_, Sqlite> for TextWrapper<Address> {
86    fn encode_by_ref(
87        &self,
88        args: &mut Vec<SqliteArgumentValue<'_>>,
89    ) -> Result<IsNull, BoxDynError> {
90        TextWrapper(self.0.0).encode_by_ref(args)
91    }
92}
93
94impl<'r> ::sqlx::Decode<'r, Sqlite> for TextWrapper<Address> {
95    fn decode(value: ::sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, BoxDynError> {
96        let text_wrapper = <TextWrapper<FixedBytes<20>> as ::sqlx::Decode<Sqlite>>::decode(value)?;
97        Ok(TextWrapper(Address(text_wrapper.0)))
98    }
99}