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