mod error;
mod raw;
mod serde;
pub use self::{
error::{Error, Result},
serde::{Serializer, SerializerOptions},
};
use std::io::Write;
use crate::{
bson::{Bson, Document},
de::MAX_BSON_SIZE,
spec::BinarySubtype,
RawDocumentBuf,
};
use ::serde::{ser::Error as SerdeError, Serialize};
pub(crate) fn write_string(buf: &mut Vec<u8>, s: &str) {
buf.extend(&(s.len() as i32 + 1).to_le_bytes());
buf.extend(s.as_bytes());
buf.push(0);
}
pub(crate) fn write_cstring(buf: &mut Vec<u8>, s: &str) -> Result<()> {
if s.contains('\0') {
return Err(Error::InvalidCString(s.into()));
}
buf.extend(s.as_bytes());
buf.push(0);
Ok(())
}
#[inline]
pub(crate) fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> Result<()> {
writer
.write_all(&val.to_le_bytes())
.map(|_| ())
.map_err(From::from)
}
#[inline]
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> Result<()> {
writer
.write_all(&val.to_le_bytes())
.map(|_| ())
.map_err(From::from)
}
#[inline]
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> Result<()> {
writer
.write_all(&val.to_le_bytes())
.map(|_| ())
.map_err(From::from)
}
#[inline]
fn write_binary<W: Write>(mut writer: W, bytes: &[u8], subtype: BinarySubtype) -> Result<()> {
let len = if let BinarySubtype::BinaryOld = subtype {
bytes.len() + 4
} else {
bytes.len()
};
if len > MAX_BSON_SIZE as usize {
return Err(Error::custom(format!(
"binary length {} exceeded maximum size",
bytes.len()
)));
}
write_i32(&mut writer, len as i32)?;
writer.write_all(&[subtype.into()])?;
if let BinarySubtype::BinaryOld = subtype {
write_i32(&mut writer, len as i32 - 4)?;
};
writer.write_all(bytes).map_err(From::from)
}
pub fn to_bson<T>(value: &T) -> Result<Bson>
where
T: Serialize + ?Sized,
{
let ser = Serializer::new();
#[cfg(feature = "serde_path_to_error")]
{
serde_path_to_error::serialize(value, ser).map_err(Error::with_path)
}
#[cfg(not(feature = "serde_path_to_error"))]
value.serialize(ser)
}
pub fn to_bson_with_options<T>(value: &T, options: SerializerOptions) -> Result<Bson>
where
T: Serialize + ?Sized,
{
let ser = Serializer::new_with_options(options);
value.serialize(ser)
}
pub fn to_document<T>(value: &T) -> Result<Document>
where
T: Serialize + ?Sized,
{
to_document_with_options(value, Default::default())
}
pub fn to_document_with_options<T>(value: &T, options: SerializerOptions) -> Result<Document>
where
T: Serialize + ?Sized,
{
match to_bson_with_options(value, options)? {
Bson::Document(doc) => Ok(doc),
bson => Err(Error::SerializationError {
message: format!(
"Could not be serialized to Document, got {:?} instead",
bson.element_type()
),
}),
}
}
#[inline]
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
where
T: Serialize,
{
let mut serializer = raw::Serializer::new();
#[cfg(feature = "serde_path_to_error")]
{
serde_path_to_error::serialize(value, &mut serializer).map_err(Error::with_path)?;
}
#[cfg(not(feature = "serde_path_to_error"))]
{
value.serialize(&mut serializer)?;
}
Ok(serializer.into_vec())
}
#[inline]
pub fn to_raw_document_buf<T>(value: &T) -> Result<RawDocumentBuf>
where
T: Serialize,
{
RawDocumentBuf::from_bytes(to_vec(value)?).map_err(Error::custom)
}