1use sqlx_core::decode::Decode;
4use sqlx_core::encode::{Encode, IsNull};
5use sqlx_core::error::BoxDynError;
6use sqlx_core::types::Type;
7
8use spg_embedded::Value as EngineValue;
9
10use crate::arguments::SpgArgumentValue;
11use crate::database::Spg;
12use crate::type_info::{Kind, SpgTypeInfo};
13use crate::value::SpgValueRef;
14
15impl Type<Spg> for i32 {
18 fn type_info() -> SpgTypeInfo {
19 SpgTypeInfo::of(Kind::Int)
20 }
21
22 fn compatible(ty: &SpgTypeInfo) -> bool {
23 matches!(ty.kind(), Kind::Int | Kind::SmallInt | Kind::BigInt)
24 }
25}
26
27impl<'q> Encode<'q, Spg> for i32 {
28 fn encode_by_ref(
29 &self,
30 buf: &mut Vec<SpgArgumentValue<'q>>,
31 ) -> Result<IsNull, BoxDynError> {
32 buf.push(SpgArgumentValue {
33 value: EngineValue::Int(*self),
34 type_info: Some(<i32 as Type<Spg>>::type_info()),
35 _phantom: core::marker::PhantomData,
36 });
37 Ok(IsNull::No)
38 }
39}
40
41impl<'r> Decode<'r, Spg> for i32 {
42 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
43 match value.engine() {
44 EngineValue::Int(n) => Ok(*n),
45 EngineValue::SmallInt(n) => Ok(i32::from(*n)),
46 EngineValue::BigInt(n) => i32::try_from(*n)
47 .map_err(|e| Box::new(e) as BoxDynError),
48 other => Err(format!("cannot decode {other:?} as i32 / INT").into()),
49 }
50 }
51}
52
53impl Type<Spg> for i64 {
56 fn type_info() -> SpgTypeInfo {
57 SpgTypeInfo::of(Kind::BigInt)
58 }
59
60 fn compatible(ty: &SpgTypeInfo) -> bool {
61 matches!(ty.kind(), Kind::BigInt | Kind::Int | Kind::SmallInt)
62 }
63}
64
65impl<'q> Encode<'q, Spg> for i64 {
66 fn encode_by_ref(
67 &self,
68 buf: &mut Vec<SpgArgumentValue<'q>>,
69 ) -> Result<IsNull, BoxDynError> {
70 buf.push(SpgArgumentValue {
71 value: EngineValue::BigInt(*self),
72 type_info: Some(<i64 as Type<Spg>>::type_info()),
73 _phantom: core::marker::PhantomData,
74 });
75 Ok(IsNull::No)
76 }
77}
78
79impl<'r> Decode<'r, Spg> for i64 {
80 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
81 match value.engine() {
82 EngineValue::BigInt(n) => Ok(*n),
83 EngineValue::Int(n) => Ok(i64::from(*n)),
84 EngineValue::SmallInt(n) => Ok(i64::from(*n)),
85 other => Err(format!("cannot decode {other:?} as i64 / BIGINT").into()),
86 }
87 }
88}
89
90impl Type<Spg> for i16 {
93 fn type_info() -> SpgTypeInfo {
94 SpgTypeInfo::of(Kind::SmallInt)
95 }
96
97 fn compatible(ty: &SpgTypeInfo) -> bool {
98 matches!(ty.kind(), Kind::SmallInt | Kind::Int | Kind::BigInt)
99 }
100}
101
102impl<'q> Encode<'q, Spg> for i16 {
103 fn encode_by_ref(
104 &self,
105 buf: &mut Vec<SpgArgumentValue<'q>>,
106 ) -> Result<IsNull, BoxDynError> {
107 buf.push(SpgArgumentValue {
108 value: EngineValue::SmallInt(*self),
109 type_info: Some(<i16 as Type<Spg>>::type_info()),
110 _phantom: core::marker::PhantomData,
111 });
112 Ok(IsNull::No)
113 }
114}
115
116impl<'r> Decode<'r, Spg> for i16 {
117 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
118 match value.engine() {
119 EngineValue::SmallInt(n) => Ok(*n),
120 EngineValue::Int(n) => i16::try_from(*n)
121 .map_err(|e| Box::new(e) as BoxDynError),
122 EngineValue::BigInt(n) => i16::try_from(*n)
123 .map_err(|e| Box::new(e) as BoxDynError),
124 other => Err(format!("cannot decode {other:?} as i16 / SMALLINT").into()),
125 }
126 }
127}