Skip to content

Commit

Permalink
Code cleanup: remove several unnecessary allocations (clone()/`to_o…
Browse files Browse the repository at this point in the history
…wned()`/`to_string()`) and ref-deref noops for `Copy` types; `#[derive]` some useful std traits for certain types for better interoperability; replace `write!(formatter, "string literal")` with `write_str()` (#100)
  • Loading branch information
Árpád Goretity  authored and zonyitoo committed Jul 27, 2018
1 parent ba45a68 commit 463cdc1
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 141 deletions.
147 changes: 72 additions & 75 deletions src/bson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,71 +87,71 @@ impl Default for Bson {

impl Debug for Bson {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Bson::FloatingPoint(p) => write!(f, "FloatingPoint({:?})", p),
&Bson::String(ref s) => write!(f, "String({:?})", s),
&Bson::Array(ref vec) => write!(f, "Array({:?})", vec),
&Bson::Document(ref doc) => write!(f, "Document({:?})", doc),
&Bson::Boolean(b) => write!(f, "Boolean({:?})", b),
&Bson::Null => write!(f, "Null"),
&Bson::RegExp(ref pat, ref opt) => write!(f, "RegExp(/{:?}/{:?})", pat, opt),
&Bson::JavaScriptCode(ref s) => write!(f, "JavaScriptCode({:?})", s),
&Bson::JavaScriptCodeWithScope(ref s, ref scope) => {
match *self {
Bson::FloatingPoint(p) => write!(f, "FloatingPoint({:?})", p),
Bson::String(ref s) => write!(f, "String({:?})", s),
Bson::Array(ref vec) => write!(f, "Array({:?})", vec),
Bson::Document(ref doc) => write!(f, "Document({:?})", doc),
Bson::Boolean(b) => write!(f, "Boolean({:?})", b),
Bson::Null => write!(f, "Null"),
Bson::RegExp(ref pat, ref opt) => write!(f, "RegExp(/{:?}/{:?})", pat, opt),
Bson::JavaScriptCode(ref s) => write!(f, "JavaScriptCode({:?})", s),
Bson::JavaScriptCodeWithScope(ref s, ref scope) => {
write!(f, "JavaScriptCodeWithScope({:?}, {:?})", s, scope)
}
&Bson::I32(v) => write!(f, "I32({:?})", v),
&Bson::I64(v) => write!(f, "I64({:?})", v),
&Bson::TimeStamp(i) => {
Bson::I32(v) => write!(f, "I32({:?})", v),
Bson::I64(v) => write!(f, "I64({:?})", v),
Bson::TimeStamp(i) => {
let time = (i >> 32) as i32;
let inc = (i & 0xFFFFFFFF) as i32;

write!(f, "TimeStamp({}, {})", time, inc)
}
&Bson::Binary(t, ref vec) => write!(f, "BinData({}, 0x{})", u8::from(t), hex::encode(vec)),
&Bson::ObjectId(ref id) => write!(f, "ObjectId({:?})", id),
&Bson::UtcDatetime(date_time) => write!(f, "UtcDatetime({:?})", date_time),
&Bson::Symbol(ref sym) => write!(f, "Symbol({:?})", sym),
Bson::Binary(t, ref vec) => write!(f, "BinData({}, 0x{})", u8::from(t), hex::encode(vec)),
Bson::ObjectId(ref id) => write!(f, "ObjectId({:?})", id),
Bson::UtcDatetime(date_time) => write!(f, "UtcDatetime({:?})", date_time),
Bson::Symbol(ref sym) => write!(f, "Symbol({:?})", sym),
}
}
}

impl Display for Bson {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
&Bson::FloatingPoint(f) => write!(fmt, "{}", f),
&Bson::String(ref s) => write!(fmt, "\"{}\"", s),
&Bson::Array(ref vec) => {
write!(fmt, "[")?;
match *self {
Bson::FloatingPoint(f) => write!(fmt, "{}", f),
Bson::String(ref s) => write!(fmt, "\"{}\"", s),
Bson::Array(ref vec) => {
fmt.write_str("[")?;

let mut first = true;
for bson in vec.iter() {
for bson in vec {
if !first {
write!(fmt, ", ")?;
fmt.write_str(", ")?;
}

write!(fmt, "{}", bson)?;
first = false;
}

write!(fmt, "]")
fmt.write_str("]")
}
&Bson::Document(ref doc) => write!(fmt, "{}", doc),
&Bson::Boolean(b) => write!(fmt, "{}", b),
&Bson::Null => write!(fmt, "null"),
&Bson::RegExp(ref pat, ref opt) => write!(fmt, "/{}/{}", pat, opt),
&Bson::JavaScriptCode(ref s) | &Bson::JavaScriptCodeWithScope(ref s, _) => fmt.write_str(&s),
&Bson::I32(i) => write!(fmt, "{}", i),
&Bson::I64(i) => write!(fmt, "{}", i),
&Bson::TimeStamp(i) => {
Bson::Document(ref doc) => write!(fmt, "{}", doc),
Bson::Boolean(b) => write!(fmt, "{}", b),
Bson::Null => write!(fmt, "null"),
Bson::RegExp(ref pat, ref opt) => write!(fmt, "/{}/{}", pat, opt),
Bson::JavaScriptCode(ref s) | Bson::JavaScriptCodeWithScope(ref s, _) => fmt.write_str(&s),
Bson::I32(i) => write!(fmt, "{}", i),
Bson::I64(i) => write!(fmt, "{}", i),
Bson::TimeStamp(i) => {
let time = (i >> 32) as i32;
let inc = (i & 0xFFFFFFFF) as i32;

write!(fmt, "Timestamp({}, {})", time, inc)
}
&Bson::Binary(t, ref vec) => write!(fmt, "BinData({}, 0x{})", u8::from(t), hex::encode(vec)),
&Bson::ObjectId(ref id) => write!(fmt, "ObjectId(\"{}\")", id),
&Bson::UtcDatetime(date_time) => write!(fmt, "Date(\"{}\")", date_time),
&Bson::Symbol(ref sym) => write!(fmt, "Symbol(\"{}\")", sym),
Bson::Binary(t, ref vec) => write!(fmt, "BinData({}, 0x{})", u8::from(t), hex::encode(vec)),
Bson::ObjectId(ref id) => write!(fmt, "ObjectId(\"{}\")", id),
Bson::UtcDatetime(date_time) => write!(fmt, "Date(\"{}\")", date_time),
Bson::Symbol(ref sym) => write!(fmt, "Symbol(\"{}\")", sym),
}
}
}
Expand Down Expand Up @@ -205,23 +205,20 @@ impl From<bool> for Bson {
}

impl From<(String, String)> for Bson {
fn from(a: (String, String)) -> Bson {
let (a1, a2) = a;
Bson::RegExp(a1.to_owned(), a2.to_owned())
fn from((pat, opt): (String, String)) -> Bson {
Bson::RegExp(pat, opt)
}
}

impl From<(String, Document)> for Bson {
fn from(a: (String, Document)) -> Bson {
let (a1, a2) = a;
Bson::JavaScriptCodeWithScope(a1, a2)
fn from((code, scope): (String, Document)) -> Bson {
Bson::JavaScriptCodeWithScope(code, scope)
}
}

impl From<(BinarySubtype, Vec<u8>)> for Bson {
fn from(a: (BinarySubtype, Vec<u8>)) -> Bson {
let (a1, a2) = a;
Bson::Binary(a1, a2)
fn from((ty, data): (BinarySubtype, Vec<u8>)) -> Bson {
Bson::Binary(ty, data)
}
}

Expand Down Expand Up @@ -257,7 +254,7 @@ impl From<[u8; 12]> for Bson {

impl From<oid::ObjectId> for Bson {
fn from(a: oid::ObjectId) -> Bson {
Bson::ObjectId(a.to_owned())
Bson::ObjectId(a)
}
}

Expand All @@ -279,16 +276,16 @@ impl From<Value> for Bson {
Value::Bool(x) => x.into(),
Value::Array(x) => Bson::Array(x.into_iter().map(Bson::from).collect()),
Value::Object(x) => {
Bson::from_extended_document(x.into_iter().map(|(k, v)| (k.clone(), v.into())).collect())
Bson::from_extended_document(x.into_iter().map(|(k, v)| (k, v.into())).collect())
}
Value::Null => Bson::Null,
}
}
}

impl Into<Value> for Bson {
fn into(self) -> Value {
match self {
impl From<Bson> for Value {
fn from(bson: Bson) -> Self {
match bson {
Bson::FloatingPoint(v) => json!(v),
Bson::String(v) => json!(v),
Bson::Array(v) => json!(v),
Expand Down Expand Up @@ -336,23 +333,23 @@ impl Into<Value> for Bson {
impl Bson {
/// Get the `ElementType` of this value.
pub fn element_type(&self) -> ElementType {
match self {
&Bson::FloatingPoint(..) => ElementType::FloatingPoint,
&Bson::String(..) => ElementType::Utf8String,
&Bson::Array(..) => ElementType::Array,
&Bson::Document(..) => ElementType::EmbeddedDocument,
&Bson::Boolean(..) => ElementType::Boolean,
&Bson::Null => ElementType::NullValue,
&Bson::RegExp(..) => ElementType::RegularExpression,
&Bson::JavaScriptCode(..) => ElementType::JavaScriptCode,
&Bson::JavaScriptCodeWithScope(..) => ElementType::JavaScriptCodeWithScope,
&Bson::I32(..) => ElementType::Integer32Bit,
&Bson::I64(..) => ElementType::Integer64Bit,
&Bson::TimeStamp(..) => ElementType::TimeStamp,
&Bson::Binary(..) => ElementType::Binary,
&Bson::ObjectId(..) => ElementType::ObjectId,
&Bson::UtcDatetime(..) => ElementType::UtcDatetime,
&Bson::Symbol(..) => ElementType::Symbol,
match *self {
Bson::FloatingPoint(..) => ElementType::FloatingPoint,
Bson::String(..) => ElementType::Utf8String,
Bson::Array(..) => ElementType::Array,
Bson::Document(..) => ElementType::EmbeddedDocument,
Bson::Boolean(..) => ElementType::Boolean,
Bson::Null => ElementType::NullValue,
Bson::RegExp(..) => ElementType::RegularExpression,
Bson::JavaScriptCode(..) => ElementType::JavaScriptCode,
Bson::JavaScriptCodeWithScope(..) => ElementType::JavaScriptCodeWithScope,
Bson::I32(..) => ElementType::Integer32Bit,
Bson::I64(..) => ElementType::Integer64Bit,
Bson::TimeStamp(..) => ElementType::TimeStamp,
Bson::Binary(..) => ElementType::Binary,
Bson::ObjectId(..) => ElementType::ObjectId,
Bson::UtcDatetime(..) => ElementType::UtcDatetime,
Bson::Symbol(..) => ElementType::Symbol,
}
}

Expand Down Expand Up @@ -437,7 +434,7 @@ impl Bson {
}

/// Converts from extended format.
/// This function mainly used for [extended JSON format](https://docs.mongodb.com/manual/reference/mongodb-extended-json/).
/// This function is mainly used for [extended JSON format](https://docs.mongodb.com/manual/reference/mongodb-extended-json/).
#[doc(hidden)]
pub fn from_extended_document(values: Document) -> Bson {
if values.len() == 2 {
Expand Down Expand Up @@ -478,7 +475,7 @@ impl Bson {
/// If `Bson` is `FloatingPoint`, return its value. Returns `None` otherwise
pub fn as_f64(&self) -> Option<f64> {
match *self {
Bson::FloatingPoint(ref v) => Some(*v),
Bson::FloatingPoint(v) => Some(v),
_ => None,
}
}
Expand Down Expand Up @@ -510,23 +507,23 @@ impl Bson {
/// If `Bson` is `Boolean`, return its value. Returns `None` otherwise
pub fn as_bool(&self) -> Option<bool> {
match *self {
Bson::Boolean(ref v) => Some(*v),
Bson::Boolean(v) => Some(v),
_ => None,
}
}

/// If `Bson` is `I32`, return its value. Returns `None` otherwise
pub fn as_i32(&self) -> Option<i32> {
match *self {
Bson::I32(ref v) => Some(*v),
Bson::I32(v) => Some(v),
_ => None,
}
}

/// If `Bson` is `I64`, return its value. Returns `None` otherwise
pub fn as_i64(&self) -> Option<i64> {
match *self {
Bson::I64(ref v) => Some(*v),
Bson::I64(v) => Some(v),
_ => None,
}
}
Expand Down Expand Up @@ -558,7 +555,7 @@ impl Bson {
/// If `Bson` is `TimeStamp`, return its value. Returns `None` otherwise
pub fn as_timestamp(&self) -> Option<i64> {
match *self {
Bson::TimeStamp(ref v) => Some(*v),
Bson::TimeStamp(v) => Some(v),
_ => None,
}
}
Expand Down Expand Up @@ -587,7 +584,7 @@ impl Bson {
/// timestamp: TimeStamp,
/// }
/// ```
#[derive(Debug, Eq, PartialEq, Clone)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
pub struct TimeStamp {
pub t: u32,
pub i: u32,
Expand Down
2 changes: 1 addition & 1 deletion src/decoder/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl fmt::Display for DecoderError {
DecoderError::ExpectedField(field_type) => write!(fmt, "expected a field of type `{}`", field_type),
DecoderError::UnknownField(ref field) => write!(fmt, "unknown field `{}`", field),
DecoderError::SyntaxError(ref inner) => inner.fmt(fmt),
DecoderError::EndOfStream => write!(fmt, "end of stream"),
DecoderError::EndOfStream => fmt.write_str("end of stream"),
DecoderError::InvalidType(ref desc) => desc.fmt(fmt),
DecoderError::InvalidLength(ref len, ref desc) => write!(fmt, "expecting length {}, {}", len, desc),
DecoderError::DuplicatedField(ref field) => write!(fmt, "duplicated field `{}`", field),
Expand Down
2 changes: 1 addition & 1 deletion src/decoder/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<'de> Visitor<'de> for BsonVisitor {
type Value = Bson;

fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expecting a Bson")
f.write_str("expecting a Bson")
}

#[inline]
Expand Down
37 changes: 18 additions & 19 deletions src/encoder/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,33 @@ impl From<io::Error> for EncoderError {

impl fmt::Display for EncoderError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
&EncoderError::IoError(ref inner) => inner.fmt(fmt),
&EncoderError::InvalidMapKeyType(ref bson) => write!(fmt, "Invalid map key type: {:?}", bson),
&EncoderError::Unknown(ref inner) => inner.fmt(fmt),
&EncoderError::UnsupportedUnsignedType => write!(fmt, "BSON does not support unsigned type"),
&EncoderError::UnsignedTypesValueExceedsRange(value) => {
write!(
fmt,
"BSON does not support unsigned types.
An attempt to encode the value: {} in a signed type failed due to the values size.",
value
)
},
match *self {
EncoderError::IoError(ref inner) => inner.fmt(fmt),
EncoderError::InvalidMapKeyType(ref bson) => write!(fmt, "Invalid map key type: {:?}", bson),
EncoderError::Unknown(ref inner) => inner.fmt(fmt),
EncoderError::UnsupportedUnsignedType => fmt.write_str("BSON does not support unsigned type"),
EncoderError::UnsignedTypesValueExceedsRange(value) => write!(
fmt,
"BSON does not support unsigned types.
An attempt to encode the value: {} in a signed type failed due to the value's size.",
value
),
}
}
}

impl error::Error for EncoderError {
fn description(&self) -> &str {
match self {
&EncoderError::IoError(ref inner) => inner.description(),
&EncoderError::InvalidMapKeyType(_) => "Invalid map key type",
&EncoderError::Unknown(ref inner) => inner,
&EncoderError::UnsupportedUnsignedType => "BSON does not support unsigned type",
&EncoderError::UnsignedTypesValueExceedsRange(_) => "BSON does not support unsigned types.
match *self {
EncoderError::IoError(ref inner) => inner.description(),
EncoderError::InvalidMapKeyType(_) => "Invalid map key type",
EncoderError::Unknown(ref inner) => inner,
EncoderError::UnsupportedUnsignedType => "BSON does not support unsigned type",
EncoderError::UnsignedTypesValueExceedsRange(_) => "BSON does not support unsigned types.
An attempt to encode the value: {} in a signed type failed due to the values size."
}
}

fn cause(&self) -> Option<&error::Error> {
match self {
&EncoderError::IoError(ref inner) => Some(inner),
Expand Down
34 changes: 17 additions & 17 deletions src/encoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,37 +102,37 @@ fn encode_bson<W: Write + ?Sized>(writer: &mut W, key: &str, val: &Bson) -> Enco
writer.write_u8(val.element_type() as u8)?;
write_cstring(writer, key)?;

match val {
&Bson::FloatingPoint(v) => write_f64(writer, v),
&Bson::String(ref v) => write_string(writer, &v),
&Bson::Array(ref v) => encode_array(writer, &v),
&Bson::Document(ref v) => encode_document(writer, v),
&Bson::Boolean(v) => writer.write_u8(if v { 0x01 } else { 0x00 }).map_err(From::from),
&Bson::RegExp(ref pat, ref opt) => {
match *val {
Bson::FloatingPoint(v) => write_f64(writer, v),
Bson::String(ref v) => write_string(writer, &v),
Bson::Array(ref v) => encode_array(writer, &v),
Bson::Document(ref v) => encode_document(writer, v),
Bson::Boolean(v) => writer.write_u8(if v { 0x01 } else { 0x00 }).map_err(From::from),
Bson::RegExp(ref pat, ref opt) => {
write_cstring(writer, pat)?;
write_cstring(writer, opt)
}
&Bson::JavaScriptCode(ref code) => write_string(writer, &code),
&Bson::ObjectId(ref id) => writer.write_all(&id.bytes()).map_err(From::from),
&Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
Bson::JavaScriptCode(ref code) => write_string(writer, &code),
Bson::ObjectId(ref id) => writer.write_all(&id.bytes()).map_err(From::from),
Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
let mut buf = Vec::new();
write_string(&mut buf, code)?;
encode_document(&mut buf, scope)?;

write_i32(writer, buf.len() as i32 + 4)?;
writer.write_all(&buf).map_err(From::from)
}
&Bson::I32(v) => write_i32(writer, v),
&Bson::I64(v) => write_i64(writer, v),
&Bson::TimeStamp(v) => write_i64(writer, v),
&Bson::Binary(subtype, ref data) => {
Bson::I32(v) => write_i32(writer, v),
Bson::I64(v) => write_i64(writer, v),
Bson::TimeStamp(v) => write_i64(writer, v),
Bson::Binary(subtype, ref data) => {
write_i32(writer, data.len() as i32)?;
writer.write_u8(From::from(subtype))?;
writer.write_all(data).map_err(From::from)
}
&Bson::UtcDatetime(ref v) => write_i64(writer, (v.timestamp() * 1000) + (v.nanosecond() / 1_000_000) as i64),
&Bson::Null => Ok(()),
&Bson::Symbol(ref v) => write_string(writer, &v),
Bson::UtcDatetime(ref v) => write_i64(writer, (v.timestamp() * 1000) + (v.nanosecond() / 1_000_000) as i64),
Bson::Null => Ok(()),
Bson::Symbol(ref v) => write_string(writer, &v),
}
}

Expand Down
Loading

0 comments on commit 463cdc1

Please # to comment.