1use crate::arguments::PgArgumentBuffer;
2use crate::type_info::{PgType, PgTypeInfo, PgTypeKind};
3use crate::types::decode::Decode;
4use crate::types::encode::{Encode, IsNull};
5use crate::types::{Oid, TypeInfo};
6use crate::value::{PgValue, PgValueFormat};
7use bytes::Buf;
8use rbdc::Error;
9use rbs::Value;
10use std::borrow::Cow;
11
12impl<T: Decode + TypeInfo> Decode for Vec<T> {
13 fn decode(value: PgValue) -> Result<Self, Error> {
14 let format = value.format();
15 match format {
16 PgValueFormat::Binary => {
17 let mut buf = value.as_bytes()?;
20
21 let ndim = buf.get_i32();
23
24 if ndim == 0 {
25 return Ok(Vec::new());
27 }
28
29 if ndim != 1 {
30 return Err(format!("encountered an array of {} dimensions; only one-dimensional arrays are supported", ndim).into());
31 }
32
33 let _flags = buf.get_i32();
37
38 let element_type_oid = Oid(buf.get_u32());
40 let element_type_info: PgTypeInfo = PgTypeInfo::try_from_oid(element_type_oid)
41 .or_else(|| value.type_info.try_array_element().map(Cow::into_owned))
42 .ok_or_else(|| {
43 Error::from(format!(
44 "failed to resolve array element type for oid {}",
45 element_type_oid.0
46 ))
47 })?;
48
49 let len = buf.get_i32();
51
52 let lower = buf.get_i32();
54
55 if lower != 1 {
56 return Err(format!("encountered an array with a lower bound of {} in the first dimension; only arrays starting at one are supported", lower).into());
57 }
58
59 let mut elements = Vec::with_capacity(len as usize);
60
61 for _ in 0..len {
62 elements.push(T::decode(PgValue::get(
63 &mut buf,
64 format,
65 element_type_info.clone(),
66 value.timezone_sec,
67 ))?)
68 }
69
70 Ok(elements)
71 }
72
73 PgValueFormat::Text => {
74 let mut element_type_info = PgTypeInfo::UNKNOWN;
76 match value.type_info.kind() {
77 PgTypeKind::Simple => {}
78 PgTypeKind::Pseudo => {}
79 PgTypeKind::Domain(_) => {}
80 PgTypeKind::Composite(_) => {}
81 PgTypeKind::Array(item) => {
82 element_type_info = item.clone();
83 }
84 PgTypeKind::Enum(_) => {}
85 PgTypeKind::Range(_) => {}
86 }
87
88 let s = value.as_str()?;
89
90 let s = &s[1..(s.len() - 1)];
94
95 if s.is_empty() {
96 return Ok(Vec::new());
98 }
99
100 let delimiter = if element_type_info.0 == crate::type_info::PgType::Box {
105 ';'
106 } else {
107 ','
108 };
109 let mut done = false;
110 let mut in_quotes = false;
111 let mut in_escape = false;
112 let timezone_sec = value.timezone_sec;
114 let mut value = String::with_capacity(10);
115 let mut chars = s.chars();
116 let mut elements = Vec::with_capacity(4);
117
118 while !done {
119 loop {
120 match chars.next() {
121 Some(ch) => match ch {
122 _ if in_escape => {
123 value.push(ch);
124 in_escape = false;
125 }
126
127 '"' => {
128 in_quotes = !in_quotes;
129 }
130
131 '\\' => {
132 in_escape = true;
133 }
134
135 _ if ch == delimiter && !in_quotes => {
136 break;
137 }
138
139 _ => {
140 value.push(ch);
141 }
142 },
143
144 None => {
145 done = true;
146 break;
147 }
148 }
149 }
150
151 let value_opt = if value == "NULL" {
152 None
153 } else {
154 Some(value.as_bytes().to_vec())
155 };
156 elements.push(T::decode(PgValue {
157 value: value_opt,
158 type_info: element_type_info.clone(),
159 format,
160 timezone_sec,
161 })?);
162
163 value.clear();
164 }
165
166 Ok(elements)
167 }
168 }
169 }
170}
171
172fn element_type_info<T: TypeInfo>(arg: &Vec<T>) -> PgTypeInfo {
173 if arg.len() == 0 {
174 PgTypeInfo::UNKNOWN
175 } else {
176 arg[0].type_info()
177 }
178}
179
180impl Encode for Vec<Value> {
181 fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
182 let type_info = element_type_info(&self);
183 buf.extend(&1_i32.to_be_bytes()); buf.extend(&0_i32.to_be_bytes()); match type_info.0 {
187 PgType::DeclareWithName(name) => buf.patch_type_by_name(&name),
188 ty => {
189 buf.extend(&ty.oid().0.to_be_bytes());
190 }
191 }
192 buf.extend(&(self.len() as i32).to_be_bytes()); buf.extend(&1_i32.to_be_bytes()); for element in self {
195 buf.encode(element)?;
196 }
197 Ok(IsNull::No)
198 }
199}