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::ValueOwned 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 f64 {
16 fn type_info() -> SpgTypeInfo {
17 SpgTypeInfo::of(Kind::Float)
18 }
19 fn compatible(ty: &SpgTypeInfo) -> bool {
20 matches!(ty.kind(), Kind::Float)
21 }
22}
23
24impl<'q> Encode<'q, Spg> for f64 {
25 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
26 buf.push(SpgArgumentValue {
27 value: EngineValue::Float(*self),
28 type_info: Some(<f64 as Type<Spg>>::type_info()),
29 _phantom: core::marker::PhantomData,
30 });
31 Ok(IsNull::No)
32 }
33}
34
35impl<'r> Decode<'r, Spg> for f64 {
36 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
37 match value.engine() {
38 EngineValue::Float(x) => Ok(*x),
39 EngineValue::Real(x) => Ok(f64::from(*x)),
41 other => Err(format!("cannot decode {other:?} as f64 / FLOAT").into()),
42 }
43 }
44}
45
46impl Type<Spg> for f32 {
47 fn type_info() -> SpgTypeInfo {
48 SpgTypeInfo::of(Kind::Float)
49 }
50 fn compatible(ty: &SpgTypeInfo) -> bool {
51 matches!(ty.kind(), Kind::Float)
52 }
53}
54
55impl<'q> Encode<'q, Spg> for f32 {
56 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
57 buf.push(SpgArgumentValue {
58 value: EngineValue::Float(f64::from(*self)),
59 type_info: Some(<f32 as Type<Spg>>::type_info()),
60 _phantom: core::marker::PhantomData,
61 });
62 Ok(IsNull::No)
63 }
64}
65
66impl<'r> Decode<'r, Spg> for f32 {
67 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
68 match value.engine() {
69 #[allow(clippy::cast_possible_truncation)]
70 EngineValue::Float(x) => Ok(*x as f32),
71 EngineValue::Real(x) => Ok(*x),
76 other => Err(format!("cannot decode {other:?} as f32 / FLOAT").into()),
77 }
78 }
79}