Skip to main content

elefant_client/types/
char.rs

1use crate::protocol::FieldDescription;
2use crate::types::{FromSqlBase, FromSqlBinary, FromSqlText, ToSql};
3use crate::PostgresType;
4use std::error::Error;
5
6impl<'a> FromSqlBase<'a> for char {
7    fn accepts_postgres_type(oid: i32) -> bool {
8        oid == PostgresType::CHAR.oid || oid == PostgresType::BPCHAR.oid
9    }
10}
11
12impl<'a> FromSqlBinary<'a> for char {
13    fn from_sql_binary(
14        raw: &'a [u8],
15        field: &FieldDescription,
16    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
17        if raw.len() != 1 {
18            return Err(format!("Invalid length for char. Expected 1 byte, got {} bytes instead. Error occurred when parsing field {:?}", raw.len(), field).into());
19        }
20
21        Ok(raw[0] as char)
22    }
23}
24
25impl<'a> FromSqlText<'a> for char {
26    fn from_sql_text(
27        raw: &'a str,
28        field: &FieldDescription,
29    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
30        if raw.is_empty() {
31            // PostgreSQL "char" type sends empty string for the zero/unset value
32            return Ok('\0');
33        }
34        if raw.len() != 1 {
35            return Err(format!("Invalid length for char. Expected 1 byte, got {} bytes instead. Error occurred when parsing field {:?}", raw.len(), field).into());
36        }
37
38        Ok(raw.chars().next().unwrap())
39    }
40}
41
42impl ToSql for char {
43    fn to_sql_binary(
44        &self,
45        target_buffer: &mut Vec<u8>,
46    ) -> Result<(), Box<dyn Error + Sync + Send>> {
47        target_buffer.push(*self as u8);
48        Ok(())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    #[cfg(feature = "tokio")]
55    mod tokio_connection {
56        use crate::test_helpers::get_settings;
57        use crate::tokio_connection::new_client;
58        use tokio::test;
59
60        #[test]
61        async fn test_char_type() {
62            let mut client = new_client(get_settings()).await.unwrap();
63
64            let c: char = client
65                .read_single_value_dual_mode("select 'a'::\"char\"")
66                .await;
67            assert_eq!(c, 'a');
68
69            let c: char = client
70                .read_single_value("select $1::\"char\";", &[&'A'])
71                .await;
72            assert_eq!(c, 'A');
73        }
74    }
75}