record_query/value/
csv.rs1use crate::error;
2use crate::value;
3use csv;
4use ordered_float;
5use std::fmt;
6use std::io;
7
8pub struct Source<R>(csv::StringRecordsIntoIter<R>)
9where
10 R: io::Read;
11
12pub struct Sink<W>(csv::Writer<W>)
13where
14 W: io::Write;
15
16#[inline]
17pub fn source<R>(r: R) -> Source<R>
18where
19 R: io::Read,
20{
21 Source(
22 csv::ReaderBuilder::new()
23 .has_headers(false)
24 .from_reader(r)
25 .into_records(),
26 )
27}
28
29#[inline]
30pub fn sink<W>(w: W) -> Sink<W>
31where
32 W: io::Write,
33{
34 Sink(csv::Writer::from_writer(w))
35}
36
37impl<R> value::Source for Source<R>
38where
39 R: io::Read,
40{
41 #[inline]
42 fn read(&mut self) -> error::Result<Option<value::Value>> {
43 match self.0.next() {
44 Some(Ok(v)) => Ok(Some(value::Value::Sequence(
45 v.iter()
46 .map(|s| value::Value::String(s.to_string()))
47 .collect(),
48 ))),
49 Some(Err(e)) => Err(error::Error::from(e)),
50 None => Ok(None),
51 }
52 }
53}
54
55impl<W> value::Sink for Sink<W>
56where
57 W: io::Write,
58{
59 #[inline]
60 fn write(&mut self, value: value::Value) -> error::Result<()> {
61 match value {
62 value::Value::Sequence(seq) => {
63 let record: Vec<String> = seq
64 .into_iter()
65 .map(value_to_csv)
66 .collect::<error::Result<Vec<_>>>()?;
67 self.0.write_record(record)?;
68 Ok(())
69 }
70 x => Err(error::Error::Format {
71 msg: format!("csv can only output sequences, got: {:?}", x),
72 }),
73 }
74 }
75}
76
77fn value_to_csv(value: value::Value) -> error::Result<String> {
78 match value {
79 value::Value::Unit => Err(error::Error::Format {
80 msg: "csv cannot output nested Unit".to_owned(),
81 }),
82 value::Value::Bool(v) => Ok(v.to_string()),
83
84 value::Value::I8(v) => Ok(v.to_string()),
85 value::Value::I16(v) => Ok(v.to_string()),
86 value::Value::I32(v) => Ok(v.to_string()),
87 value::Value::I64(v) => Ok(v.to_string()),
88
89 value::Value::U8(v) => Ok(v.to_string()),
90 value::Value::U16(v) => Ok(v.to_string()),
91 value::Value::U32(v) => Ok(v.to_string()),
92 value::Value::U64(v) => Ok(v.to_string()),
93
94 value::Value::F32(ordered_float::OrderedFloat(v)) => Ok(v.to_string()),
95 value::Value::F64(ordered_float::OrderedFloat(v)) => Ok(v.to_string()),
96
97 value::Value::Char(v) => Ok(v.to_string()),
98 value::Value::String(v) => Ok(v),
99 value::Value::Bytes(_) => Err(error::Error::Format {
100 msg: "csv cannot output nested bytes".to_owned(),
101 }),
102
103 value::Value::Sequence(_) => Err(error::Error::Format {
104 msg: "csv cannot output nested sequences".to_owned(),
105 }),
106 value::Value::Map(_) => Err(error::Error::Format {
107 msg: "csv cannot output nested maps".to_owned(),
108 }),
109 }
110}
111
112impl<R> fmt::Debug for Source<R>
113where
114 R: io::Read,
115{
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 f.debug_struct("CsvSource").finish()
118 }
119}
120
121impl<W> fmt::Debug for Sink<W>
122where
123 W: io::Write,
124{
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 f.debug_struct("CsvSink").finish()
127 }
128}