rbdc_pg/types/
json.rs

1use crate::arguments::PgArgumentBuffer;
2use crate::type_info::PgTypeInfo;
3use crate::types::decode::Decode;
4use crate::types::encode::{Encode, IsNull};
5use crate::types::TypeInfo;
6use crate::value::{PgValue, PgValueFormat};
7use rbdc::json::Json;
8use rbdc::Error;
9use rbs::Value;
10use std::io::Write;
11
12impl Encode for Json {
13    fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
14        let mut bytes = self.0.into_bytes();
15        if bytes.is_empty() {
16            bytes = "null".to_string().into_bytes();
17        }
18        // we have a tiny amount of dynamic behavior depending if we are resolved to be JSON
19        // instead of JSONB
20        buf.patch(|buf, ty: &PgTypeInfo| {
21            if *ty == PgTypeInfo::JSON || *ty == PgTypeInfo::JSON_ARRAY {
22                buf[0] = b' ';
23            }
24        });
25
26        // JSONB version (as of 2020-03-20)
27        buf.push(1);
28
29        // the JSON data written to the buffer is the same regardless of parameter type
30        buf.write_all(&bytes)?;
31
32        Ok(IsNull::No)
33    }
34}
35
36impl Decode for Json {
37    fn decode(value: PgValue) -> Result<Self, Error> {
38        let fmt = value.format();
39        let type_info = value.type_info;
40        let mut buf = value.value.unwrap_or_default();
41        if buf.len() == 0 {
42            return Ok(Json {
43                0: "null".to_string(),
44            });
45        }
46        if fmt == PgValueFormat::Binary && type_info == PgTypeInfo::JSONB {
47            assert_eq!(
48                buf[0], 1,
49                "unsupported JSONB format version {}; please open an issue",
50                buf[0]
51            );
52            buf.remove(0);
53        }
54        Ok(Self {
55            0: String::from_utf8_lossy(&buf).into_owned(),
56        })
57    }
58}
59
60pub fn decode_json(value: PgValue) -> Result<Value, Error> {
61    let fmt = value.format();
62    let type_info = value.type_info;
63    let mut buf = value.value.unwrap_or_default();
64    if buf.len() == 0 {
65        return Ok(Value::Null);
66    }
67    if fmt == PgValueFormat::Binary && type_info == PgTypeInfo::JSONB {
68        assert_eq!(
69            buf[0], 1,
70            "unsupported JSONB format version {}; please open an issue",
71            buf[0]
72        );
73        buf.remove(0);
74    }
75    Ok(serde_json::from_str(&String::from_utf8_lossy(&buf))
76        .map_err(|e| Error::from(e.to_string()))?)
77}
78
79pub fn encode_json(v: Value, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
80    // we have a tiny amount of dynamic behavior depending if we are resolved to be JSON
81    // instead of JSONB
82    buf.patch(|buf, ty: &PgTypeInfo| {
83        if *ty == PgTypeInfo::JSON || *ty == PgTypeInfo::JSON_ARRAY {
84            buf[0] = b' ';
85        }
86    });
87
88    // JSONB version (as of 2020-03-20)
89    buf.push(1);
90
91    // the JSON data written to the buffer is the same regardless of parameter type
92    buf.write_all(&v.to_string().into_bytes())?;
93
94    Ok(IsNull::No)
95}
96
97impl TypeInfo for Json {
98    fn type_info(&self) -> PgTypeInfo {
99        PgTypeInfo::JSONB
100    }
101}