Skip to main content

nautilus_blockchain/cache/
types.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::str::FromStr;
17
18use alloy::primitives::{I256, U160, U256};
19use sqlx::{
20    Database, Decode, Encode, Postgres, Type,
21    encode::IsNull,
22    error::BoxDynError,
23    postgres::{PgHasArrayType, PgTypeInfo},
24};
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct I256Pg(pub I256);
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct U256Pg(pub U256);
31
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct U160Pg(pub U160);
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub struct U128Pg(pub u128);
37
38macro_rules! impl_pg_numeric {
39    ($wrapper:ty, $inner:ty, $pg_type:literal, $display_name:literal) => {
40        impl Type<Postgres> for $wrapper {
41            fn type_info() -> PgTypeInfo {
42                PgTypeInfo::with_name($pg_type)
43            }
44        }
45
46        // PostgreSQL numeric values require decimal Display encoding
47        impl<'q> Encode<'q, Postgres> for $wrapper {
48            fn encode_by_ref(
49                &self,
50                buf: &mut <Postgres as Database>::ArgumentBuffer,
51            ) -> Result<IsNull, BoxDynError> {
52                let value = self.0.to_string();
53                <&str as Encode<Postgres>>::encode(&value, buf)
54            }
55        }
56
57        impl<'r> Decode<'r, Postgres> for $wrapper {
58            fn decode(
59                value: sqlx::postgres::PgValueRef<'r>,
60            ) -> Result<Self, sqlx::error::BoxDynError> {
61                let value = <String as Decode<Postgres>>::decode(value)?;
62                let value = <$inner>::from_str(&value)
63                    .map_err(|e| format!("Failed to parse {}: {e}", $display_name))?;
64                Ok(Self(value))
65            }
66        }
67
68        impl PgHasArrayType for $wrapper {
69            fn array_type_info() -> PgTypeInfo {
70                PgTypeInfo::with_name(concat!("_", $pg_type))
71            }
72        }
73    };
74}
75
76impl_pg_numeric!(I256Pg, I256, "i256", "I256");
77impl_pg_numeric!(U256Pg, U256, "u256", "U256");
78impl_pg_numeric!(U160Pg, U160, "u160", "U160");
79impl_pg_numeric!(U128Pg, u128, "u128", "U128");