|
23 | 23 |
|
24 | 24 | use std::fmt::{Display, Error, Formatter};
|
25 | 25 |
|
26 |
| -use chrono::{DateTime, UTC}; |
| 26 | +use chrono::{DateTime, Timelike, UTC}; |
| 27 | +use chrono::offset::TimeZone; |
27 | 28 | use rustc_serialize::json;
|
28 |
| -use rustc_serialize::hex::ToHex; |
| 29 | +use rustc_serialize::hex::{FromHex, ToHex}; |
29 | 30 |
|
30 | 31 | use ordered::OrderedDocument;
|
31 | 32 | use spec::{ElementType, BinarySubtype};
|
@@ -290,4 +291,85 @@ impl Bson {
|
290 | 291 | &json::Json::Null => Bson::Null,
|
291 | 292 | }
|
292 | 293 | }
|
| 294 | + |
| 295 | + pub fn to_extended_document(&self) -> Document { |
| 296 | + match *self { |
| 297 | + Bson::RegExp(ref pat, ref opt) => { |
| 298 | + doc! { |
| 299 | + "$regex" => (pat.clone()), |
| 300 | + "$options" => (opt.clone()) |
| 301 | + } |
| 302 | + } |
| 303 | + Bson::JavaScriptCode(ref code) => { |
| 304 | + doc! { |
| 305 | + "$code" => (code.clone()) |
| 306 | + } |
| 307 | + } |
| 308 | + Bson::JavaScriptCodeWithScope(ref code, ref scope) => { |
| 309 | + doc! { |
| 310 | + "$code" => (code.clone()), |
| 311 | + "$scope" => (scope.clone()) |
| 312 | + } |
| 313 | + } |
| 314 | + Bson::TimeStamp(v) => { |
| 315 | + // TODO |
| 316 | + doc! { |
| 317 | + //"$timestamp" => { |
| 318 | +// "t" => (v[0..4] as i32), |
| 319 | + //"i" => (v[4..8] as i32), |
| 320 | + "$timestamp" => v |
| 321 | + } |
| 322 | + } |
| 323 | + Bson::Binary(t, ref v) => { |
| 324 | + let tval: u8 = From::from(t); |
| 325 | + doc! { |
| 326 | + "$binary" => (v.to_hex()), |
| 327 | + "type" => (tval as i64) |
| 328 | + } |
| 329 | + } |
| 330 | + Bson::ObjectId(ref v) => { |
| 331 | + doc! { |
| 332 | + "$oid" => (v.to_string()) |
| 333 | + } |
| 334 | + } |
| 335 | + Bson::UtcDatetime(ref v) => { |
| 336 | + doc! { |
| 337 | + "$date" => { |
| 338 | + "$numberLong" => ((v.timestamp() * 1000) + (v.nanosecond() / 1000000) as i64) |
| 339 | + } |
| 340 | + } |
| 341 | + } |
| 342 | + // TODO: Actual error |
| 343 | + _ => unreachable!() |
| 344 | + } |
| 345 | + } |
| 346 | + |
| 347 | + pub fn from_extended_document(values: Document) -> Result<Bson, Error> { |
| 348 | + if let Some(&Bson::String(ref pat)) = values.get("$regex") { |
| 349 | + if let Some(&Bson::String(ref opt)) = values.get("$options") { |
| 350 | + return Ok(Bson::RegExp(pat.to_owned(), opt.to_owned())); |
| 351 | + } |
| 352 | + } else if let Some(&Bson::String(ref code)) = values.get("$code") { |
| 353 | + if let Some(&Bson::Document(ref scope)) = values.get("$sscope") { |
| 354 | + return Ok(Bson::JavaScriptCodeWithScope(code.to_owned(), scope.to_owned())); |
| 355 | + } else { |
| 356 | + return Ok(Bson::JavaScriptCode(code.to_owned())); |
| 357 | + } |
| 358 | + } else if values.contains_key("$timestamp") { |
| 359 | + // TODO |
| 360 | + } else if let Some(&Bson::String(ref hex)) = values.get("$binary") { |
| 361 | + if let Some(&Bson::I64(t)) = values.get("type") { |
| 362 | + let ttype = t as u8; |
| 363 | + return Ok(Bson::Binary(From::from(ttype), hex.from_hex().unwrap())); |
| 364 | + } |
| 365 | + } else if let Some(&Bson::String(ref hex)) = values.get("$oid") { |
| 366 | + return Ok(Bson::ObjectId(oid::ObjectId::with_string(hex).unwrap())); |
| 367 | + } else if let Some(&Bson::Document(ref doc)) = values.get("$date") { |
| 368 | + if let Some(&Bson::I64(long)) = doc.get("$numberLong") { |
| 369 | + return Ok(Bson::UtcDatetime(UTC.timestamp(long / 1000, (long % 1000) as u32 * 1000000))); |
| 370 | + } |
| 371 | + } |
| 372 | + |
| 373 | + Ok(Bson::Document(values)) |
| 374 | + } |
293 | 375 | }
|
0 commit comments