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