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