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(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
29 buf.push(SpgArgumentValue {
30 value: EngineValue::Int(*self),
31 type_info: Some(<i32 as Type<Spg>>::type_info()),
32 _phantom: core::marker::PhantomData,
33 });
34 Ok(IsNull::No)
35 }
36}
37
38impl<'r> Decode<'r, Spg> for i32 {
39 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
40 match value.engine() {
41 EngineValue::Int(n) => Ok(*n),
42 EngineValue::SmallInt(n) => Ok(i32::from(*n)),
43 EngineValue::BigInt(n) => i32::try_from(*n).map_err(|e| Box::new(e) as BoxDynError),
44 other => Err(format!("cannot decode {other:?} as i32 / INT").into()),
45 }
46 }
47}
48
49impl Type<Spg> for i64 {
52 fn type_info() -> SpgTypeInfo {
53 SpgTypeInfo::of(Kind::BigInt)
54 }
55
56 fn compatible(ty: &SpgTypeInfo) -> bool {
57 matches!(ty.kind(), Kind::BigInt | Kind::Int | Kind::SmallInt)
58 }
59}
60
61impl<'q> Encode<'q, Spg> for i64 {
62 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
63 buf.push(SpgArgumentValue {
64 value: EngineValue::BigInt(*self),
65 type_info: Some(<i64 as Type<Spg>>::type_info()),
66 _phantom: core::marker::PhantomData,
67 });
68 Ok(IsNull::No)
69 }
70}
71
72impl<'r> Decode<'r, Spg> for i64 {
73 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
74 match value.engine() {
75 EngineValue::BigInt(n) => Ok(*n),
76 EngineValue::Int(n) => Ok(i64::from(*n)),
77 EngineValue::SmallInt(n) => Ok(i64::from(*n)),
78 other => Err(format!("cannot decode {other:?} as i64 / BIGINT").into()),
79 }
80 }
81}
82
83impl Type<Spg> for i16 {
86 fn type_info() -> SpgTypeInfo {
87 SpgTypeInfo::of(Kind::SmallInt)
88 }
89
90 fn compatible(ty: &SpgTypeInfo) -> bool {
91 matches!(ty.kind(), Kind::SmallInt | Kind::Int | Kind::BigInt)
92 }
93}
94
95impl<'q> Encode<'q, Spg> for i16 {
96 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
97 buf.push(SpgArgumentValue {
98 value: EngineValue::SmallInt(*self),
99 type_info: Some(<i16 as Type<Spg>>::type_info()),
100 _phantom: core::marker::PhantomData,
101 });
102 Ok(IsNull::No)
103 }
104}
105
106impl<'r> Decode<'r, Spg> for i16 {
107 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
108 match value.engine() {
109 EngineValue::SmallInt(n) => Ok(*n),
110 EngineValue::Int(n) => i16::try_from(*n).map_err(|e| Box::new(e) as BoxDynError),
111 EngineValue::BigInt(n) => i16::try_from(*n).map_err(|e| Box::new(e) as BoxDynError),
112 other => Err(format!("cannot decode {other:?} as i16 / SMALLINT").into()),
113 }
114 }
115}