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!(
28 ty.kind(),
29 Kind::Text | Kind::Numeric | Kind::Vector | Kind::TsVector | Kind::Uuid
30 )
31 }
32}
33
34impl Type<Spg> for String {
35 fn type_info() -> SpgTypeInfo {
36 <str as Type<Spg>>::type_info()
37 }
38
39 fn compatible(ty: &SpgTypeInfo) -> bool {
40 <str as Type<Spg>>::compatible(ty)
41 }
42}
43
44impl<'q> Encode<'q, Spg> for &'q str {
45 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
46 buf.push(SpgArgumentValue {
47 value: EngineValue::Text((*self).to_string()),
48 type_info: Some(<str as Type<Spg>>::type_info()),
49 _phantom: core::marker::PhantomData,
50 });
51 Ok(IsNull::No)
52 }
53}
54
55impl<'q> Encode<'q, Spg> for String {
56 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
57 buf.push(SpgArgumentValue {
58 value: EngineValue::Text(self.clone()),
59 type_info: Some(<String as Type<Spg>>::type_info()),
60 _phantom: core::marker::PhantomData,
61 });
62 Ok(IsNull::No)
63 }
64}
65
66impl<'r> Decode<'r, Spg> for String {
67 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
68 if let Some(s) = crate::types::decimal::try_numeric_as_string(value.engine()) {
74 return Ok(s);
75 }
76 if let Some(s) = crate::types::vector::try_vector_as_string(value.engine()) {
77 return Ok(s);
78 }
79 if let Some(s) = crate::types::vector::try_tsvector_as_string(value.engine()) {
80 return Ok(s);
81 }
82 if let Some(s) = crate::types::uuid::try_uuid_as_string(value.engine()) {
83 return Ok(s);
84 }
85 match value.engine() {
86 EngineValue::Text(s) | EngineValue::Json(s) => Ok(s.clone()),
87 other => Err(format!("cannot decode {other:?} as String / TEXT").into()),
88 }
89 }
90}
91
92impl<'r> Decode<'r, Spg> for &'r str {
93 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
94 match value.engine() {
95 EngineValue::Text(s) | EngineValue::Json(s) => Ok(s.as_str()),
96 other => Err(format!("cannot decode {other:?} as &str / TEXT").into()),
97 }
98 }
99}