Skip to main content

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::{PgValueFormat, PgValueRef};
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: PgValueRef) -> Result<Self, Error> {
38        let fmt = value.format();
39        let type_info = value.type_info;
40        let 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            Ok(Self {
53                0: String::from_utf8_lossy(&buf[1..]).into_owned(),
54            })
55        } else {
56            Ok(Self {
57                0: String::from_utf8_lossy(&buf).into_owned(),
58            })
59        }
60    }
61}
62
63pub fn decode_json(value: PgValueRef) -> Result<Value, Error> {
64    let fmt = value.format();
65    let type_info = value.type_info;
66    let buf = value.value.unwrap_or_default();
67    if buf.len() == 0 {
68        return Ok(Value::Null);
69    }
70    if fmt == PgValueFormat::Binary && type_info == PgTypeInfo::JSONB {
71        assert_eq!(
72            buf[0], 1,
73            "unsupported JSONB format version {}; please open an issue",
74            buf[0]
75        );
76        Ok(serde_json::from_str(&String::from_utf8_lossy(&buf[1..]))
77            .map_err(|e| Error::from(e.to_string()))?)
78    } else {
79        Ok(serde_json::from_str(&String::from_utf8_lossy(&buf))
80            .map_err(|e| Error::from(e.to_string()))?)
81    }
82}
83
84pub fn encode_json(v: Value, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
85    // we have a tiny amount of dynamic behavior depending if we are resolved to be JSON
86    // instead of JSONB
87    buf.patch(|buf, ty: &PgTypeInfo| {
88        if *ty == PgTypeInfo::JSON || *ty == PgTypeInfo::JSON_ARRAY {
89            buf[0] = b' ';
90        }
91    });
92
93    // JSONB version (as of 2020-03-20)
94    buf.push(1);
95
96    // the JSON data written to the buffer is the same regardless of parameter type
97    buf.write_all(&v.to_string().into_bytes())?;
98
99    Ok(IsNull::No)
100}
101
102impl TypeInfo for Json {
103    fn type_info(&self) -> PgTypeInfo {
104        PgTypeInfo::JSONB
105    }
106}