Skip to content

Commit 7c1e0eb

Browse files
committed
Replaced Decoder struct with free function.
1 parent 0c25c25 commit 7c1e0eb

File tree

4 files changed

+141
-184
lines changed

4 files changed

+141
-184
lines changed

examples/decode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fs::File;
55
fn main() {
66
let mut f = File::open("examples/test.bson").unwrap();
77

8-
while let Ok(decoded) = bson::Decoder::new(&mut f).decode_document() {
8+
while let Ok(decoded) = bson::decode_document(&mut f) {
99
println!("{:?}", decoded);
1010
}
1111
}

src/decoder.rs

Lines changed: 106 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -91,205 +91,131 @@ impl error::Error for DecoderError {
9191

9292
pub type DecoderResult<T> = Result<T, DecoderError>;
9393

94-
pub struct Decoder<'a> {
95-
reader: &'a mut Read,
96-
}
97-
98-
impl<'a> Decoder<'a> {
99-
pub fn new(r: &'a mut Read) -> Decoder<'a> {
100-
Decoder {
101-
reader: r,
102-
}
103-
}
104-
105-
fn read_string(&mut self) -> Result<String, DecoderError> {
106-
let len = try!(self.reader.read_i32::<LittleEndian>());
107-
108-
let mut s = String::new();
109-
try!(self.reader.take(len as u64 - 1).read_to_string(&mut s));
110-
try!(self.reader.read_u8()); // The last 0x00
111-
112-
Ok(s)
113-
}
114-
115-
fn read_cstring(&mut self) -> Result<String, DecoderError> {
116-
let mut v = Vec::new();
117-
118-
loop {
119-
let c = try!(self.reader.read_u8());
120-
if c == 0 { break; }
121-
v.push(c);
122-
}
123-
124-
Ok(try!(str::from_utf8(&v)).to_owned())
125-
}
126-
127-
pub fn decode_floating_point(&mut self) -> Result<f64, DecoderError> {
128-
self.reader.read_f64::<LittleEndian>().map_err(From::from)
129-
}
130-
131-
pub fn decode_utf8_string(&mut self) -> Result<String, DecoderError> {
132-
self.read_string()
133-
}
134-
135-
pub fn decode_binary_data(&mut self) -> Result<(BinarySubtype, Vec<u8>), DecoderError> {
136-
let len = try!(self.reader.read_i32::<LittleEndian>());
137-
let t = BinarySubtype::from(try!(self.reader.read_u8()));
138-
let mut data = Vec::new();
139-
try!(self.reader.take(len as u64).read_to_end(&mut data));
140-
141-
Ok((t, data))
142-
}
143-
144-
pub fn decode_objectid(&mut self) -> Result<[u8; 12], DecoderError> {
145-
let mut objid = [0u8; 12];
146-
147-
for x in objid.iter_mut() {
148-
*x = try!(self.reader.read_u8());
149-
}
150-
151-
Ok(objid)
152-
}
153-
154-
pub fn decode_boolean(&mut self) -> Result<bool, DecoderError> {
155-
let x = try!(self.reader.read_u8());
156-
Ok(x != 0x00)
157-
}
158-
159-
pub fn decode_regexp(&mut self) -> Result<(String, String), DecoderError> {
160-
let pat = try!(self.read_cstring());
161-
let opt = try!(self.read_cstring());
162-
163-
Ok((pat, opt))
164-
}
94+
fn read_string<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<String> {
95+
let len = try!(reader.read_i32::<LittleEndian>());
16596

166-
pub fn decode_javascript_code(&mut self) -> Result<String, DecoderError> {
167-
self.read_string()
168-
}
169-
170-
pub fn decode_javascript_code_with_scope(&mut self) -> Result<(String, Document), DecoderError> {
171-
let code = try!(self.read_string());
172-
let doc = try!(self.decode_document());
173-
Ok((code, doc))
174-
}
97+
let mut s = String::with_capacity(len as usize - 1);
98+
try!(reader.take(len as u64 - 1).read_to_string(&mut s));
99+
try!(reader.read_u8()); // The last 0x00
175100

176-
pub fn decode_integer_32bit(&mut self) -> Result<i32, DecoderError> {
177-
self.reader.read_i32::<LittleEndian>().map_err(From::from)
178-
}
101+
Ok(s)
102+
}
179103

180-
pub fn decode_integer_64bit(&mut self) -> Result<i64, DecoderError> {
181-
self.reader.read_i64::<LittleEndian>().map_err(From::from)
182-
}
104+
fn read_cstring<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<String> {
105+
let mut v = Vec::new();
183106

184-
pub fn decode_timestamp(&mut self) -> Result<i64, DecoderError> {
185-
self.reader.read_i64::<LittleEndian>().map_err(From::from)
186-
}
107+
loop {
108+
let c = try!(reader.read_u8());
109+
if c == 0 { break; }
110+
v.push(c);
111+
}
187112

188-
pub fn decode_utc_datetime(&mut self) -> Result<DateTime<UTC>, DecoderError> {
189-
let x = try!(self.reader.read_i64::<LittleEndian>());
113+
Ok(try!(str::from_utf8(&v)).to_owned())
114+
}
190115

191-
let d = DateTime::from_utc(NaiveDateTime::from_timestamp(x, 0), UTC);
116+
fn read_i32<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<i32> {
117+
reader.read_i32::<LittleEndian>().map_err(From::from)
118+
}
192119

193-
Ok(d)
194-
}
120+
fn read_i64<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<i64> {
121+
reader.read_i64::<LittleEndian>().map_err(From::from)
122+
}
195123

196-
pub fn decode_document(&mut self) -> Result<Document, DecoderError> {
197-
let mut doc = Document::new();
124+
pub fn decode_document<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<Document> {
125+
let mut doc = Document::new();
198126

199-
try!(self.reader.read_i32::<LittleEndian>()); // Total length, we don't need it
127+
// disregard the length: using Read::take causes infinite type recursion
128+
try!(read_i32(reader));
200129

201-
loop {
202-
let t = try!(self.reader.read_u8());
130+
loop {
131+
let tag = try!(reader.read_u8());
203132

204-
if t == 0 {
205-
break;
206-
}
133+
if tag == 0 {
134+
break;
135+
}
207136

208-
let k = try!(self.read_cstring());
209-
let v = try!(self.decode_bson(t));
137+
let key = try!(read_cstring(reader));
138+
let val = try!(decode_bson(reader, tag));
210139

211-
doc.insert(k, v);
212-
}
140+
doc.insert(key, val);
141+
}
213142

214-
Ok(doc)
215-
}
143+
Ok(doc)
144+
}
216145

217-
pub fn decode_array(&mut self) -> Result<Array, DecoderError> {
218-
let mut arr = Array::new();
146+
fn decode_array<R: Read + ?Sized>(reader: &mut R) -> DecoderResult<Array> {
147+
let mut arr = Array::new();
219148

220-
try!(self.reader.read_i32::<LittleEndian>()); // Total length, we don't need it
149+
// disregard the length: using Read::take causes infinite type recursion
150+
try!(read_i32(reader));
221151

222-
loop {
223-
let t = try!(self.reader.read_u8());
224-
if t == 0 {
225-
break;
226-
}
152+
loop {
153+
let tag = try!(reader.read_u8());
154+
if tag == 0 {
155+
break;
156+
}
227157

228-
let k = try!(self.read_cstring());
229-
if k != &arr.len().to_string()[..] {
230-
return Err(DecoderError::InvalidArrayKey(arr.len(), k));
231-
}
232-
let v = try!(self.decode_bson(t));
158+
// check that the key is as expected
159+
let key = try!(read_cstring(reader));
160+
if key != &arr.len().to_string()[..] {
161+
return Err(DecoderError::InvalidArrayKey(arr.len(), key));
162+
}
233163

234-
arr.push(v)
235-
}
164+
let val = try!(decode_bson(reader, tag));
165+
arr.push(val)
166+
}
236167

237-
Ok(arr)
238-
}
168+
Ok(arr)
169+
}
239170

240-
fn decode_bson(&mut self, tag: u8) -> Result<Bson, DecoderError> {
241-
match tag {
242-
spec::ELEMENT_TYPE_FLOATING_POINT => {
243-
self.decode_floating_point().map(Bson::FloatingPoint)
244-
},
245-
spec::ELEMENT_TYPE_UTF8_STRING => {
246-
self.decode_utf8_string().map(Bson::String)
247-
},
248-
spec::ELEMENT_TYPE_EMBEDDED_DOCUMENT => {
249-
self.decode_document().map(Bson::Document)
250-
},
251-
spec::ELEMENT_TYPE_ARRAY => {
252-
self.decode_array().map(Bson::Array)
253-
},
254-
spec::ELEMENT_TYPE_BINARY => {
255-
self.decode_binary_data().map(|(t, dat)| Bson::Binary(t, dat))
256-
},
257-
spec::ELEMENT_TYPE_OBJECT_ID => {
258-
self.decode_objectid().map(Bson::ObjectId)
259-
},
260-
spec::ELEMENT_TYPE_BOOLEAN => {
261-
self.decode_boolean().map(Bson::Boolean)
262-
},
263-
spec::ELEMENT_TYPE_NULL_VALUE => {
264-
Ok(Bson::Null)
265-
},
266-
spec::ELEMENT_TYPE_REGULAR_EXPRESSION => {
267-
self.decode_regexp().map(|(pat, opt)| Bson::RegExp(pat, opt))
268-
},
269-
spec::ELEMENT_TYPE_JAVASCRIPT_CODE => {
270-
self.decode_javascript_code().map(Bson::JavaScriptCode)
271-
},
272-
spec::ELEMENT_TYPE_JAVASCRIPT_CODE_WITH_SCOPE => {
273-
self.decode_javascript_code_with_scope().map(
274-
|(code, scope)| Bson::JavaScriptCodeWithScope(code, scope)
275-
)
276-
},
277-
spec::ELEMENT_TYPE_DEPRECATED => {
278-
Ok(Bson::Deprecated)
279-
},
280-
spec::ELEMENT_TYPE_32BIT_INTEGER => {
281-
self.decode_integer_32bit().map(Bson::I32)
282-
},
283-
spec::ELEMENT_TYPE_64BIT_INTEGER => {
284-
self.decode_integer_64bit().map(Bson::I64)
285-
},
286-
spec::ELEMENT_TYPE_TIMESTAMP => {
287-
self.decode_timestamp().map(Bson::TimeStamp)
288-
},
289-
spec::ELEMENT_TYPE_UTC_DATETIME => {
290-
self.decode_utc_datetime().map(Bson::UtcDatetime)
291-
},
292-
_ => Err(DecoderError::UnrecognizedElementType(tag)),
293-
}
294-
}
171+
fn decode_bson<R: Read + ?Sized>(reader: &mut R, tag: u8) -> DecoderResult<Bson> {
172+
use spec::ElementType::*;
173+
match spec::ElementType::from(tag) {
174+
Some(FloatingPoint) => {
175+
Ok(Bson::FloatingPoint(try!(reader.read_f64::<LittleEndian>())))
176+
},
177+
Some(Utf8String) => read_string(reader).map(Bson::String),
178+
Some(EmbeddedDocument) => decode_document(reader).map(Bson::Document),
179+
Some(Array) => decode_array(reader).map(Bson::Array),
180+
Some(Binary) => {
181+
let len = try!(read_i32(reader));
182+
let subtype = BinarySubtype::from(try!(reader.read_u8()));
183+
let mut data = Vec::with_capacity(len as usize);
184+
try!(reader.take(len as u64).read_to_end(&mut data));
185+
Ok(Bson::Binary(subtype, data))
186+
}
187+
Some(ObjectId) => {
188+
let mut objid = [0; 12];
189+
for x in &mut objid {
190+
*x = try!(reader.read_u8());
191+
}
192+
Ok(Bson::ObjectId(objid))
193+
}
194+
Some(Boolean) => Ok(Bson::Boolean(try!(reader.read_u8()) != 0)),
195+
Some(NullValue) => Ok(Bson::Null),
196+
Some(RegularExpression) => {
197+
let pat = try!(read_cstring(reader));
198+
let opt = try!(read_cstring(reader));
199+
Ok(Bson::RegExp(pat, opt))
200+
},
201+
Some(JavaScriptCode) => read_string(reader).map(Bson::JavaScriptCode),
202+
Some(JavaScriptCodeWithScope) => {
203+
let code = try!(read_string(reader));
204+
let scope = try!(decode_document(reader));
205+
Ok(Bson::JavaScriptCodeWithScope(code, scope))
206+
},
207+
Some(Deprecated) => Ok(Bson::Deprecated),
208+
Some(Integer32Bit) => read_i32(reader).map(Bson::I32),
209+
Some(Integer64Bit) => read_i64(reader).map(Bson::I64),
210+
Some(TimeStamp) => read_i64(reader).map(Bson::TimeStamp),
211+
Some(UtcDatetime) => {
212+
let time = try!(read_i64(reader));
213+
Ok(Bson::UtcDatetime(DateTime::from_utc(NaiveDateTime::from_timestamp(time, 0), UTC)))
214+
},
215+
Some(Undefined) |
216+
Some(DbPointer) |
217+
Some(MaxKey) |
218+
Some(MinKey) |
219+
None => Err(DecoderError::UnrecognizedElementType(tag))
220+
}
295221
}

src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,11 @@ extern crate byteorder;
5555

5656
pub use self::bson::{Bson, ToBson, Document, Array};
5757
pub use self::encoder::{Encoder, EncoderResult, EncoderError};
58-
pub use self::decoder::{Decoder, DecoderResult, DecoderError};
58+
pub use self::decoder::{decode_document, DecoderResult, DecoderError};
5959

60-
pub mod bson;
60+
mod bson;
6161
pub mod spec;
6262

6363
pub mod encoder;
64-
pub mod decoder;
64+
mod decoder;
65+

src/spec.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,36 @@ pub enum ElementType {
8080
MinKey = ELEMENT_TYPE_MINKEY,
8181
}
8282

83+
impl ElementType {
84+
#[inline]
85+
pub fn from(tag: u8) -> Option<ElementType> {
86+
use self::ElementType::*;
87+
Some(match tag {
88+
ELEMENT_TYPE_FLOATING_POINT => FloatingPoint,
89+
ELEMENT_TYPE_UTF8_STRING => Utf8String,
90+
ELEMENT_TYPE_EMBEDDED_DOCUMENT => EmbeddedDocument,
91+
ELEMENT_TYPE_ARRAY => Array,
92+
ELEMENT_TYPE_BINARY => Binary,
93+
ELEMENT_TYPE_UNDEFINED => Undefined,
94+
ELEMENT_TYPE_OBJECT_ID => ObjectId,
95+
ELEMENT_TYPE_BOOLEAN => Boolean,
96+
ELEMENT_TYPE_UTC_DATETIME => UtcDatetime,
97+
ELEMENT_TYPE_NULL_VALUE => NullValue,
98+
ELEMENT_TYPE_REGULAR_EXPRESSION => RegularExpression,
99+
ELEMENT_TYPE_DBPOINTER => DbPointer,
100+
ELEMENT_TYPE_JAVASCRIPT_CODE => JavaScriptCode,
101+
ELEMENT_TYPE_DEPRECATED => Deprecated,
102+
ELEMENT_TYPE_JAVASCRIPT_CODE_WITH_SCOPE => JavaScriptCodeWithScope,
103+
ELEMENT_TYPE_32BIT_INTEGER => Integer32Bit,
104+
ELEMENT_TYPE_TIMESTAMP => TimeStamp,
105+
ELEMENT_TYPE_64BIT_INTEGER => Integer64Bit,
106+
ELEMENT_TYPE_MAXKEY => MaxKey,
107+
ELEMENT_TYPE_MINKEY => MinKey,
108+
_ => return None
109+
})
110+
}
111+
}
112+
83113
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
84114
pub enum BinarySubtype {
85115
Generic,

0 commit comments

Comments
 (0)