Skip to content

Commit 1ca4ef4

Browse files
committed
init commit for v0.0.1
0 parents  commit 1ca4ef4

File tree

8 files changed

+896
-0
lines changed

8 files changed

+896
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "bson-rs"
3+
version = "0.0.1"
4+
authors = ["Y. T. Chung <[email protected]>"]
5+
description = "Encoding and decoding support for BSON in Rust"
6+
license = "MIT"
7+
readme = "README.md"
8+
homepage = "https://github.com/zonyitoo/bson-rs"
9+
10+
[lib]
11+
name = "bson"
12+
13+
[dependencies]
14+
chrono = "*"
15+
byteorder = "*"

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# bson-rs
2+
3+
Encoding and decoding support for BSON in Rust
4+
5+
```toml
6+
[dependencies]
7+
bson-rs = "*"
8+
```

src/bson.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// The MIT License (MIT)
2+
3+
// Copyright (c) 2015 Y. T. Chung <[email protected]>
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
// this software and associated documentation files (the "Software"), to deal in
7+
// the Software without restriction, including without limitation the rights to
8+
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
// the Software, and to permit persons to whom the Software is furnished to do so,
10+
// subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
use std::collections::BTreeMap;
23+
use std::string;
24+
25+
use chrono::{DateTime, UTC};
26+
27+
use spec::BinarySubtype;
28+
29+
#[derive(Debug, Clone)]
30+
pub enum Bson {
31+
FloatingPoint(f64),
32+
String(String),
33+
Array(self::Array),
34+
Document(self::Document),
35+
Boolean(bool),
36+
Null,
37+
RegExp(string::String, string::String),
38+
JavaScriptCode(string::String),
39+
JavaScriptCodeWithScope(string::String, self::Document),
40+
Deprecated,
41+
I32(i32),
42+
I64(i64),
43+
TimeStamp(i64),
44+
Binary(BinarySubtype, Vec<u8>),
45+
ObjectId([u8; 12]),
46+
UtcDatetime(DateTime<UTC>),
47+
}
48+
49+
pub type Array = Vec<Bson>;
50+
pub type Document = BTreeMap<String, Bson>;

src/decoder.rs

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
// The MIT License (MIT)
2+
3+
// Copyright (c) 2015 Y. T. Chung <[email protected]>
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
// this software and associated documentation files (the "Software"), to deal in
7+
// the Software without restriction, including without limitation the rights to
8+
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
// the Software, and to permit persons to whom the Software is furnished to do so,
10+
// subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
use std::io::{self, Read};
23+
use std::str;
24+
use std::convert::From;
25+
26+
use byteorder::{self, LittleEndian, ReadBytesExt};
27+
use chrono::{DateTime, NaiveDateTime, UTC};
28+
29+
use spec::{self, BinarySubtype};
30+
use bson;
31+
32+
#[derive(Debug)]
33+
pub enum DecoderError {
34+
IoError(io::Error),
35+
Utf8Error(str::Utf8Error),
36+
UnrecognizedElementType(u8),
37+
}
38+
39+
impl From<io::Error> for DecoderError {
40+
fn from(err: io::Error) -> DecoderError {
41+
DecoderError::IoError(err)
42+
}
43+
}
44+
45+
impl From<str::Utf8Error> for DecoderError {
46+
fn from(err: str::Utf8Error) -> DecoderError {
47+
DecoderError::Utf8Error(err)
48+
}
49+
}
50+
51+
52+
impl From<byteorder::Error> for DecoderError {
53+
fn from(err: byteorder::Error) -> DecoderError {
54+
DecoderError::IoError(From::from(err))
55+
}
56+
}
57+
58+
pub type DecoderResult<T> = Result<T, DecoderError>;
59+
60+
pub struct Decoder<'a> {
61+
reader: &'a mut Read,
62+
}
63+
64+
impl<'a> Decoder<'a> {
65+
pub fn new(r: &'a mut Read) -> Decoder<'a> {
66+
Decoder {
67+
reader: r,
68+
}
69+
}
70+
71+
fn read_string(&mut self) -> Result<String, DecoderError> {
72+
let len = try!(self.reader.read_i32::<LittleEndian>());
73+
74+
let mut s = String::new();
75+
try!(self.reader.take(len as u64 - 1).read_to_string(&mut s));
76+
try!(self.reader.read_u8()); // The last 0x00
77+
78+
Ok(s)
79+
}
80+
81+
fn read_cstring(&mut self) -> Result<String, DecoderError> {
82+
let mut v = Vec::new();
83+
84+
loop {
85+
let c = try!(self.reader.read_u8());
86+
if c == 0 { break; }
87+
v.push(c);
88+
}
89+
90+
Ok(try!(str::from_utf8(&v[..])).to_string())
91+
}
92+
93+
pub fn decode_floating_point(&mut self) -> Result<f64, DecoderError> {
94+
let f = try!(self.reader.read_f64::<LittleEndian>());
95+
Ok(f)
96+
}
97+
98+
pub fn decode_utf8_string(&mut self) -> Result<String, DecoderError> {
99+
self.read_string()
100+
}
101+
102+
pub fn decode_binary_data(&mut self) -> Result<(BinarySubtype, Vec<u8>), DecoderError> {
103+
let len = try!(self.reader.read_i32::<LittleEndian>());
104+
let t: BinarySubtype = From::from(try!(self.reader.read_u8()));
105+
let mut data = Vec::new();
106+
try!(self.reader.take(len as u64).read_to_end(&mut data));
107+
108+
Ok((t, data))
109+
}
110+
111+
pub fn decode_objectid(&mut self) -> Result<[u8; 12], DecoderError> {
112+
let mut objid = [0u8; 12];
113+
114+
for x in objid.iter_mut() {
115+
*x = try!(self.reader.read_u8());
116+
}
117+
118+
Ok(objid)
119+
}
120+
121+
pub fn decode_boolean(&mut self) -> Result<bool, DecoderError> {
122+
let x = try!(self.reader.read_u8());
123+
124+
if x == 0x00 {
125+
Ok(false)
126+
} else {
127+
Ok(true)
128+
}
129+
}
130+
131+
pub fn decode_regexp(&mut self) -> Result<(String, String), DecoderError> {
132+
let pat = try!(self.read_cstring());
133+
let opt = try!(self.read_cstring());
134+
135+
Ok((pat, opt))
136+
}
137+
138+
pub fn decode_javascript_code(&mut self) -> Result<String, DecoderError> {
139+
let code = try!(self.read_string());
140+
141+
Ok(code)
142+
}
143+
144+
pub fn decode_javascript_code_with_scope(&mut self) -> Result<(String, bson::Document), DecoderError> {
145+
let code = try!(self.read_string());
146+
let doc = try!(self.decode_document());
147+
148+
Ok((code, doc))
149+
}
150+
151+
pub fn decode_integer_32bit(&mut self) -> Result<i32, DecoderError> {
152+
let x = try!(self.reader.read_i32::<LittleEndian>());
153+
154+
Ok(x)
155+
}
156+
157+
pub fn decode_integer_64bit(&mut self) -> Result<i64, DecoderError> {
158+
let x = try!(self.reader.read_i64::<LittleEndian>());
159+
160+
Ok(x)
161+
}
162+
163+
pub fn decode_timestamp(&mut self) -> Result<i64, DecoderError> {
164+
let x = try!(self.reader.read_i64::<LittleEndian>());
165+
166+
Ok(x)
167+
}
168+
169+
pub fn decode_utc_datetime(&mut self) -> Result<DateTime<UTC>, DecoderError> {
170+
let x = try!(self.reader.read_i64::<LittleEndian>());
171+
172+
let d = DateTime::from_utc(NaiveDateTime::from_timestamp(x, 0), UTC);
173+
174+
Ok(d)
175+
}
176+
177+
pub fn decode_document(&mut self) -> Result<bson::Document, DecoderError> {
178+
let mut doc = bson::Document::new();
179+
180+
try!(self.reader.read_i32::<LittleEndian>()); // Total length, we don't need it
181+
182+
loop {
183+
let t = try!(self.reader.read_u8());
184+
185+
if t == 0 {
186+
break;
187+
}
188+
189+
let (k, v) = try!(self.decode_bson(t));
190+
191+
doc.insert(k, v);
192+
}
193+
194+
Ok(doc)
195+
}
196+
197+
pub fn decode_array(&mut self) -> Result<bson::Array, DecoderError> {
198+
let mut arr = bson::Array::new();
199+
200+
try!(self.reader.read_i32::<LittleEndian>()); // Total length, we don't need it
201+
202+
loop {
203+
let t = try!(self.reader.read_u8());
204+
if t == 0 {
205+
break;
206+
}
207+
// TODO: Ignore the key or not?
208+
let (_, v) = try!(self.decode_bson(t));
209+
210+
arr.push(v)
211+
}
212+
213+
Ok(arr)
214+
}
215+
216+
fn decode_bson(&mut self, t: u8) -> Result<(String, bson::Bson), DecoderError> {
217+
let res = match t {
218+
spec::ELEMENT_TYPE_FLOATING_POINT => {
219+
let key = try!(self.read_cstring());
220+
let val = try!(self.decode_floating_point());
221+
222+
(key, bson::Bson::FloatingPoint(val))
223+
},
224+
spec::ELEMENT_TYPE_UTF8_STRING => {
225+
let key = try!(self.read_cstring());
226+
let val = try!(self.decode_utf8_string());
227+
228+
(key, bson::Bson::String(val))
229+
},
230+
spec::ELEMENT_TYPE_EMBEDDED_DOCUMENT => {
231+
let key = try!(self.read_cstring());
232+
let val = try!(self.decode_document());
233+
234+
(key, bson::Bson::Document(val))
235+
},
236+
spec::ELEMENT_TYPE_ARRAY => {
237+
let key = try!(self.read_cstring());
238+
let val = try!(self.decode_array());
239+
240+
(key, bson::Bson::Array(val))
241+
},
242+
spec::ELEMENT_TYPE_BINARY => {
243+
let key = try!(self.read_cstring());
244+
let (t, dat) = try!(self.decode_binary_data());
245+
246+
(key, bson::Bson::Binary(t, dat))
247+
},
248+
spec::ELEMENT_TYPE_OBJECT_ID => {
249+
let key = try!(self.read_cstring());
250+
let val = try!(self.decode_objectid());
251+
252+
(key, bson::Bson::ObjectId(val))
253+
},
254+
spec::ELEMENT_TYPE_BOOLEAN => {
255+
let key = try!(self.read_cstring());
256+
let val = try!(self.decode_boolean());
257+
258+
(key, bson::Bson::Boolean(val))
259+
},
260+
spec::ELEMENT_TYPE_NULL_VALUE => {
261+
let key = try!(self.read_cstring());
262+
263+
(key, bson::Bson::Null)
264+
},
265+
spec::ELEMENT_TYPE_REGULAR_EXPRESSION => {
266+
let key = try!(self.read_cstring());
267+
let (pat, opt) = try!(self.decode_regexp());
268+
269+
(key, bson::Bson::RegExp(pat, opt))
270+
},
271+
spec::ELEMENT_TYPE_JAVASCRIPT_CODE => {
272+
let key = try!(self.read_cstring());
273+
let code = try!(self.decode_javascript_code());
274+
275+
(key, bson::Bson::JavaScriptCode(code))
276+
},
277+
spec::ELEMENT_TYPE_JAVASCRIPT_CODE_WITH_SCOPE => {
278+
let key = try!(self.read_cstring());
279+
let (code, scope) = try!(self.decode_javascript_code_with_scope());
280+
281+
(key, bson::Bson::JavaScriptCodeWithScope(code, scope))
282+
},
283+
spec::ELEMENT_TYPE_DEPRECATED => {
284+
let key = try!(self.read_cstring());
285+
286+
(key, bson::Bson::Deprecated)
287+
},
288+
spec::ELEMENT_TYPE_32BIT_INTEGER => {
289+
let key = try!(self.read_cstring());
290+
let val = try!(self.decode_integer_32bit());
291+
292+
(key, bson::Bson::I32(val))
293+
},
294+
spec::ELEMENT_TYPE_64BIT_INTEGER => {
295+
let key = try!(self.read_cstring());
296+
let val = try!(self.decode_integer_64bit());
297+
298+
(key, bson::Bson::I64(val))
299+
},
300+
spec::ELEMENT_TYPE_TIMESTAMP => {
301+
let key = try!(self.read_cstring());
302+
let val = try!(self.decode_timestamp());
303+
304+
(key, bson::Bson::TimeStamp(val))
305+
},
306+
spec::ELEMENT_TYPE_UTC_DATETIME => {
307+
let key = try!(self.read_cstring());
308+
let val = try!(self.decode_utc_datetime());
309+
310+
(key, bson::Bson::UtcDatetime(val))
311+
},
312+
_ => return Err(DecoderError::UnrecognizedElementType(t)),
313+
};
314+
315+
Ok(res)
316+
}
317+
}

0 commit comments

Comments
 (0)