1#![expect(
18 clippy::inline_always,
19 reason = "Just unification helpers of 1-2 lines of casting types"
20)]
21#![expect(
22 dead_code,
23 reason = "Not all converters are used bidirectionally, however, keeping them is a good thing"
24)]
25#![expect(
26 clippy::cast_sign_loss,
27 reason = "This is the one file where we map the signed database types to the working types"
28)]
29#![expect(
30 clippy::cast_possible_wrap,
31 reason = "We will not approach the item count where i64 and usize casting will cause issues
32 on relevant platforms"
33)]
34
35use miden_protocol::Felt;
36use miden_protocol::account::{StorageSlotName, StorageSlotType};
37use miden_protocol::block::BlockNumber;
38use miden_protocol::note::NoteTag;
39
40#[derive(Debug, thiserror::Error)]
41#[error("failed to convert from database type {from_type} into {into_type}")]
42pub struct DatabaseTypeConversionError {
43 source: Box<dyn std::error::Error + Send + Sync>,
44 from_type: &'static str,
45 into_type: &'static str,
46}
47
48pub trait SqlTypeConvert: Sized {
52 type Raw: Sized;
53
54 fn to_raw_sql(self) -> Self::Raw;
55 fn from_raw_sql(_raw: Self::Raw) -> Result<Self, DatabaseTypeConversionError>;
56
57 fn map_err<E: std::error::Error + Send + Sync + 'static>(
58 source: E,
59 ) -> DatabaseTypeConversionError {
60 DatabaseTypeConversionError {
61 source: Box::new(source),
62 from_type: std::any::type_name::<Self::Raw>(),
63 into_type: std::any::type_name::<Self>(),
64 }
65 }
66}
67
68impl SqlTypeConvert for BlockNumber {
69 type Raw = i64;
70
71 fn from_raw_sql(raw: Self::Raw) -> Result<Self, DatabaseTypeConversionError> {
72 u32::try_from(raw).map(BlockNumber::from).map_err(Self::map_err)
73 }
74
75 fn to_raw_sql(self) -> Self::Raw {
76 i64::from(self.as_u32())
77 }
78}
79
80impl SqlTypeConvert for NoteTag {
81 type Raw = i32;
82
83 #[inline(always)]
84 fn from_raw_sql(raw: Self::Raw) -> Result<Self, DatabaseTypeConversionError> {
85 #[expect(clippy::cast_sign_loss)]
86 Ok(NoteTag::new(raw as u32))
87 }
88
89 #[inline(always)]
90 fn to_raw_sql(self) -> Self::Raw {
91 self.as_u32() as i32
92 }
93}
94
95impl SqlTypeConvert for StorageSlotType {
96 type Raw = i32;
97
98 #[inline(always)]
99 fn from_raw_sql(raw: Self::Raw) -> Result<Self, DatabaseTypeConversionError> {
100 #[derive(Debug, thiserror::Error)]
101 #[error("invalid storage slot type value {0}")]
102 struct ValueError(i32);
103
104 Ok(match raw {
105 0 => StorageSlotType::Value,
106 1 => StorageSlotType::Map,
107 invalid => {
108 return Err(Self::map_err(ValueError(invalid)));
109 },
110 })
111 }
112
113 #[inline(always)]
114 fn to_raw_sql(self) -> Self::Raw {
115 match self {
116 StorageSlotType::Value => 0,
117 StorageSlotType::Map => 1,
118 }
119 }
120}
121
122impl SqlTypeConvert for StorageSlotName {
123 type Raw = String;
124
125 fn from_raw_sql(raw: Self::Raw) -> Result<Self, DatabaseTypeConversionError> {
126 StorageSlotName::new(raw).map_err(Self::map_err)
127 }
128
129 fn to_raw_sql(self) -> Self::Raw {
130 String::from(self)
131 }
132}
133
134#[inline(always)]
138pub(crate) fn raw_sql_to_nullifier_prefix(raw: i32) -> u16 {
139 debug_assert!(raw >= 0);
140 raw as u16
141}
142#[inline(always)]
143pub(crate) fn nullifier_prefix_to_raw_sql(prefix: u16) -> i32 {
144 i32::from(prefix)
145}
146
147#[inline(always)]
148pub(crate) fn raw_sql_to_nonce(raw: i64) -> Felt {
149 debug_assert!(raw >= 0);
150 Felt::new(raw as u64)
151}
152#[inline(always)]
153pub(crate) fn nonce_to_raw_sql(nonce: Felt) -> i64 {
154 nonce.as_int() as i64
155}
156
157#[inline(always)]
158pub(crate) fn raw_sql_to_fungible_delta(raw: i64) -> i64 {
159 raw
160}
161#[inline(always)]
162pub(crate) fn fungible_delta_to_raw_sql(delta: i64) -> i64 {
163 delta
164}
165
166#[inline(always)]
167#[expect(clippy::cast_sign_loss)]
168pub(crate) fn raw_sql_to_note_type(raw: i32) -> u8 {
169 raw as u8
170}
171#[inline(always)]
172pub(crate) fn note_type_to_raw_sql(note_type: u8) -> i32 {
173 i32::from(note_type)
174}
175
176#[inline(always)]
177pub(crate) fn raw_sql_to_idx(raw: i32) -> usize {
178 raw as usize
179}
180#[inline(always)]
181pub(crate) fn idx_to_raw_sql(idx: usize) -> i32 {
182 idx as i32
183}