sonnerie/
row_format.rs

1//! Decode an encoded row format.
2
3use byteorder::{BigEndian, ByteOrder};
4use escape_string::split_one;
5
6use crate::Timestamp;
7
8/// Decodes a row by its format. Created with [`parse_row_format`](fn.parse_row_format.html).
9pub trait RowFormat {
10	/// Encode the data into `dest` into the binary format that is stored.
11	fn to_stored_format(&self, ts: Timestamp, from: &str, dest: &mut Vec<u8>)
12		-> Result<(), String>;
13	/// Decode the data into something human readable
14	fn elements(&self) -> &[Box<dyn Element>];
15	/// The size in bytes of a row payload, including its timestamp.
16	///
17	/// None indicates that it has a variable-sized encoding (Strings)
18	fn row_size(&self) -> Option<usize>;
19}
20
21struct RowFormatImpl {
22	size: Option<usize>,
23	elements: Vec<Box<dyn Element>>,
24}
25
26impl RowFormat for RowFormatImpl {
27	fn to_stored_format(
28		&self,
29		ts: Timestamp,
30		mut from: &str,
31		dest: &mut Vec<u8>,
32	) -> Result<(), String> {
33		let at = dest.len();
34		dest.reserve(at + self.row_size().unwrap_or(0) + 8);
35		dest.resize(at + 8, 0);
36		BigEndian::write_u64(&mut dest[at..], ts);
37		for e in self.elements.iter() {
38			from = e.to_stored_format(from, dest)?;
39		}
40		if !from.is_empty() {
41			return Err("too many columns in input".to_string());
42		}
43		Ok(())
44	}
45	fn elements(&self) -> &[Box<dyn Element>] {
46		&self.elements
47	}
48	fn row_size(&self) -> Option<usize> {
49		Some(self.size? + 8)
50	}
51}
52
53/// convert a text-based row format description to an object
54///
55/// the text format is one character per term, these are the characters:
56///
57/// * `i` -> 32-bit signed integer
58/// * `I` -> 64-bit signed integer
59/// * `u` -> 32-bit unsigned integer
60/// * `U` -> 64-bit unsigned integer
61/// * `f` -> 32-bit unsigned float
62/// * `F` -> 64-bit unsigned float
63/// * `s` -> variable size string type
64///
65/// Potential future types:
66/// * decimal
67/// * large integers, floats (128 bit, 256 bit)
68/// to indicate "typical size"). The typical size is useful
69/// for knowing how big to make the blocks
70pub fn parse_row_format(human: &str) -> Box<dyn RowFormat> {
71	let mut size = 0usize;
72	let mut has_size = true;
73	let mut elements: Vec<Box<dyn Element>> = Vec::with_capacity(human.len());
74
75	for t in human.bytes() {
76		match t {
77			b'i' => {
78				size += 4;
79				elements.push(Box::new(ElementI32));
80			}
81			b'u' => {
82				size += 4;
83				elements.push(Box::new(ElementU32));
84			}
85			b'I' => {
86				size += 8;
87				elements.push(Box::new(ElementI64));
88			}
89			b'U' => {
90				size += 8;
91				elements.push(Box::new(ElementU64));
92			}
93			b'f' => {
94				size += 4;
95				elements.push(Box::new(ElementF32));
96			}
97			b'F' => {
98				size += 8;
99				elements.push(Box::new(ElementF64));
100			}
101			b's' => {
102				has_size = false;
103				elements.push(Box::new(ElementString));
104			}
105			a => {
106				panic!("invalid format character '{}'", a);
107			}
108		}
109	}
110
111	Box::new(RowFormatImpl {
112		size: if has_size { Some(size) } else { None },
113		elements,
114	})
115}
116
117pub fn row_format_size(human: &str) -> Option<usize> {
118	let human = human.as_bytes();
119
120	let mut size = 0usize;
121
122	for t in human {
123		match t {
124			b'i' => size += 4,
125			b'u' => size += 4,
126			b'I' => size += 8,
127			b'U' => size += 8,
128			b'f' => size += 4,
129			b'F' => size += 8,
130			b's' => return None,
131			b'\x7f' => return None,
132			a => {
133				panic!("invalid format character '{}'", a);
134			}
135		}
136	}
137
138	Some(size)
139}
140
141pub trait Element {
142	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String>;
143	fn to_protocol_format<'a>(
144		&self,
145		from: &'a [u8],
146		dest: &mut dyn ::std::io::Write,
147	) -> ::std::io::Result<&'a [u8]>;
148}
149
150struct ElementI32;
151impl Element for ElementI32 {
152	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
153		let at = dest.len();
154		dest.resize(at + 4, 0);
155		let dest = &mut dest[at..];
156
157		let (t, rest) = split_one(from).unwrap();
158
159		let v = t
160			.parse()
161			.map_err(|e| format!("while parsing {}: {}", t, e))?;
162		BigEndian::write_i32(dest, v);
163
164		Ok(rest)
165	}
166	fn to_protocol_format<'a>(
167		&self,
168		from: &'a [u8],
169		dest: &mut dyn ::std::io::Write,
170	) -> ::std::io::Result<&'a [u8]> {
171		let v: i32 = BigEndian::read_i32(&from[0..4]);
172		write!(dest, "{}", v)?;
173		Ok(&from[4..])
174	}
175}
176
177struct ElementU32;
178impl Element for ElementU32 {
179	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
180		let at = dest.len();
181		dest.resize(at + 4, 0);
182		let dest = &mut dest[at..];
183
184		let (t, rest) = split_one(from).unwrap();
185
186		let v = t
187			.parse()
188			.map_err(|e| format!("while parsing {}: {}", t, e))?;
189		BigEndian::write_u32(dest, v);
190
191		Ok(rest)
192	}
193	fn to_protocol_format<'a>(
194		&self,
195		from: &'a [u8],
196		dest: &mut dyn ::std::io::Write,
197	) -> ::std::io::Result<&'a [u8]> {
198		let v: u32 = BigEndian::read_u32(&from[0..4]);
199		write!(dest, "{}", v)?;
200		Ok(&from[4..])
201	}
202}
203
204struct ElementI64;
205impl Element for ElementI64 {
206	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
207		let at = dest.len();
208		dest.resize(at + 8, 0);
209		let dest = &mut dest[at..];
210
211		let (t, rest) = split_one(from).unwrap();
212
213		let v = t
214			.parse()
215			.map_err(|e| format!("while parsing {}: {}", t, e))?;
216		BigEndian::write_i64(dest, v);
217
218		Ok(rest)
219	}
220	fn to_protocol_format<'a>(
221		&self,
222		from: &'a [u8],
223		dest: &mut dyn ::std::io::Write,
224	) -> ::std::io::Result<&'a [u8]> {
225		let v: i64 = BigEndian::read_i64(&from[0..8]);
226		write!(dest, "{}", v)?;
227		Ok(&from[8..])
228	}
229}
230
231struct ElementU64;
232impl Element for ElementU64 {
233	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
234		let at = dest.len();
235		dest.resize(at + 8, 0);
236		let dest = &mut dest[at..];
237
238		let (t, rest) = split_one(from).unwrap();
239
240		let v = t
241			.parse()
242			.map_err(|e| format!("while parsing {}: {}", t, e))?;
243		BigEndian::write_u64(dest, v);
244
245		Ok(rest)
246	}
247	fn to_protocol_format<'a>(
248		&self,
249		from: &'a [u8],
250		dest: &mut dyn ::std::io::Write,
251	) -> ::std::io::Result<&'a [u8]> {
252		let v: u64 = BigEndian::read_u64(&from[0..8]);
253		write!(dest, "{}", v)?;
254		Ok(&from[8..])
255	}
256}
257
258struct ElementF32;
259impl Element for ElementF32 {
260	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
261		let at = dest.len();
262		dest.resize(at + 4, 0);
263		let dest = &mut dest[at..];
264
265		let (t, rest) = split_one(from).unwrap();
266
267		let v = if t == "nan" {
268			::std::f32::NAN
269		} else {
270			t.parse()
271				.map_err(|e| format!("while parsing {}: {}", t, e))?
272		};
273		BigEndian::write_f32(dest, v);
274
275		Ok(rest)
276	}
277	fn to_protocol_format<'a>(
278		&self,
279		from: &'a [u8],
280		dest: &mut dyn ::std::io::Write,
281	) -> ::std::io::Result<&'a [u8]> {
282		let v: f32 = BigEndian::read_f32(&from[0..4]);
283		write!(dest, "{:.17}", v)?;
284		Ok(&from[4..])
285	}
286}
287
288struct ElementF64;
289impl Element for ElementF64 {
290	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
291		let at = dest.len();
292		dest.resize(at + 8, 0);
293		let dest = &mut dest[at..];
294
295		let (t, rest) = split_one(from).unwrap();
296
297		let v = if t == "nan" {
298			::std::f64::NAN
299		} else {
300			t.parse()
301				.map_err(|e| format!("while parsing {}: {}", t, e))?
302		};
303		BigEndian::write_f64(dest, v);
304
305		Ok(rest)
306	}
307	fn to_protocol_format<'a>(
308		&self,
309		from: &'a [u8],
310		dest: &mut dyn ::std::io::Write,
311	) -> ::std::io::Result<&'a [u8]> {
312		let v: f64 = BigEndian::read_f64(&from[0..8]);
313		write!(dest, "{:.17}", v)?;
314		Ok(&from[8..])
315	}
316}
317
318pub(crate) struct ElementString;
319impl Element for ElementString {
320	fn to_stored_format<'s>(&self, from: &'s str, dest: &mut Vec<u8>) -> Result<&'s str, String> {
321		let (head, tail) = escape_string::split_one(from)
322			.ok_or_else(|| format!("Unable to parse \"{}\" as backslash-escaped string", from))?;
323		let mut buf = unsigned_varint::encode::u64_buffer();
324		let encoded_len = unsigned_varint::encode::u64(head.len() as u64, &mut buf);
325		dest.extend_from_slice(encoded_len);
326		dest.extend_from_slice(head.as_bytes());
327		Ok(tail)
328	}
329	fn to_protocol_format<'a>(
330		&self,
331		from: &'a [u8],
332		dest: &mut dyn ::std::io::Write,
333	) -> ::std::io::Result<&'a [u8]> {
334		let (len, tail) = unsigned_varint::decode::u64(from).map_err(|e| {
335			std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{:?}", e))
336		})?;
337
338		let s = std::str::from_utf8(&tail[0..len as usize])
339			.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
340		write!(dest, "{}", escape_string::escape(s))?;
341		Ok(&tail[len as usize..])
342	}
343}