zero_postgres/conversion/
string.rs1use crate::error::{Error, Result};
4use crate::protocol::types::{Oid, oid};
5
6use super::{FromWireValue, ToWireValue};
7
8impl<'a> FromWireValue<'a> for &'a str {
9 fn from_text(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
10 if !matches!(
12 oid,
13 oid::TEXT | oid::VARCHAR | oid::BPCHAR | oid::NAME | oid::NUMERIC
14 ) {
15 return Err(Error::Decode(format!("cannot decode oid {} as str", oid)));
16 }
17 simdutf8::compat::from_utf8(bytes)
18 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))
19 }
20
21 fn from_binary(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
22 if !matches!(oid, oid::TEXT | oid::VARCHAR | oid::BPCHAR | oid::NAME) {
24 return Err(Error::Decode(format!("cannot decode oid {} as str", oid)));
25 }
26 simdutf8::compat::from_utf8(bytes)
27 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))
28 }
29}
30
31impl FromWireValue<'_> for String {
32 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
33 if !matches!(
35 oid,
36 oid::TEXT | oid::VARCHAR | oid::BPCHAR | oid::NAME | oid::NUMERIC
37 ) {
38 return Err(Error::Decode(format!(
39 "cannot decode oid {} as String",
40 oid
41 )));
42 }
43 simdutf8::compat::from_utf8(bytes)
44 .map(|s| s.to_owned())
45 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))
46 }
47
48 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
49 if !matches!(oid, oid::TEXT | oid::VARCHAR | oid::BPCHAR | oid::NAME) {
51 return Err(Error::Decode(format!(
52 "cannot decode oid {} as String",
53 oid
54 )));
55 }
56 simdutf8::compat::from_utf8(bytes)
57 .map(|s| s.to_owned())
58 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))
59 }
60}
61
62impl ToWireValue for str {
63 fn natural_oid(&self) -> Oid {
64 oid::TEXT
65 }
66
67 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
68 match target_oid {
69 oid::TEXT | oid::VARCHAR | oid::BPCHAR | oid::NAME | oid::JSON | oid::JSONB => {
70 let bytes = self.as_bytes();
71 buf.extend_from_slice(&(bytes.len() as i32).to_be_bytes());
72 buf.extend_from_slice(bytes);
73 Ok(())
74 }
75 _ => Err(Error::type_mismatch(self.natural_oid(), target_oid)),
76 }
77 }
78}
79
80impl ToWireValue for String {
81 fn natural_oid(&self) -> Oid {
82 oid::TEXT
83 }
84
85 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
86 self.as_str().encode(target_oid, buf)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_string_text() {
96 assert_eq!(String::from_text(oid::TEXT, b"hello").unwrap(), "hello");
97 }
98
99 #[test]
100 fn test_type_mismatch() {
101 assert!(String::from_binary(oid::INT4, &[0, 0, 0, 1]).is_err());
103 }
104}