#![cfg_attr( feature = "external_doc", feature(external_doc) )]
#![cfg_attr( feature = "external_doc", doc(include = "../README.md") )]
#![ doc ( html_root_url = "https://docs.rs/futures_cbor_codec" ) ]
#![ deny ( missing_docs ) ]
#![ forbid ( unsafe_code ) ]
#![ allow ( clippy::suspicious_else_formatting ) ]
#![ warn
(
missing_debug_implementations ,
missing_docs ,
nonstandard_style ,
rust_2018_idioms ,
trivial_casts ,
trivial_numeric_casts ,
unused_extern_crates ,
unused_qualifications ,
unreachable_pub ,
variant_size_differences ,
)]
use
{
std::
{
error :: { Error as ErrorTrait } ,
fmt :: { { Display, Formatter, Result as FmtResult } } ,
io :: { { Error as IoError, Read, Result as IoResult, Write } } ,
marker :: { PhantomData } ,
},
bytes :: { BytesMut } ,
serde :: { { Deserialize, Serialize} } ,
serde_cbor :: { de::{Deserializer, IoRead}, error::Error as CborError } ,
serde_cbor :: { ser::{IoWrite, Serializer} } ,
futures_codec :: { {Decoder as IoDecoder, Encoder as IoEncoder } } ,
};
#[ allow( variant_size_differences ) ]
#[derive(Debug)]
pub enum Error
{
Io(IoError),
Cbor(CborError),
#[doc(hidden)]
__NonExhaustive__,
}
impl From<IoError> for Error {
fn from(error: IoError) -> Self {
Error::Io(error)
}
}
impl From<CborError> for Error {
fn from(error: CborError) -> Self {
Error::Cbor(error)
}
}
impl Display for Error {
fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
match self {
Error::Io(e) => e.fmt(fmt),
Error::Cbor(e) => e.fmt(fmt),
Error::__NonExhaustive__ => unreachable!(),
}
}
}
impl ErrorTrait for Error {
fn cause(&self) -> Option<&dyn ErrorTrait> {
match self {
Error::Io(e) => Some(e),
Error::Cbor(e) => Some(e),
Error::__NonExhaustive__ => unreachable!(),
}
}
}
struct Counted<'a, R>
{
r : &'a mut R ,
pos: &'a mut usize,
}
impl<R: Read> Read for Counted<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
match self.r.read(buf) {
Ok(size) => {
*self.pos += size;
Ok(size)
},
e => e,
}
}
}
#[derive(Clone, Debug)]
pub struct Decoder<Item> {
_data: PhantomData<fn() -> Item>,
}
impl<'de, Item: Deserialize<'de>> Decoder<Item>
{
pub fn new() -> Self
{
Self { _data: PhantomData }
}
}
impl<'de, Item: Deserialize<'de>> Default for Decoder<Item>
{
fn default() -> Self
{
Self::new()
}
}
impl<'de, Item: Deserialize<'de>> IoDecoder for Decoder<Item>
{
type Item = Item ;
type Error = Error ;
fn decode( &mut self, src: &mut BytesMut ) -> Result<Option<Item>, Error>
{
let mut pos = 0;
let mut slice: &[u8] = src;
let reader = IoRead::new( Counted
{
r : &mut slice ,
pos: &mut pos ,
});
let mut deserializer = Deserializer::new(reader);
match Item::deserialize( &mut deserializer )
{
Ok(item) =>
{
src.split_to(pos);
Ok(Some(item))
},
Err( ref error ) if error.is_eof() => Ok( None ),
Err(e) => Err( e.into() ),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SdMode
{
Always,
Once,
Never,
}
#[derive(Clone, Debug)]
pub struct Encoder<Item>
{
_data: PhantomData<fn(Item)>,
sd: SdMode,
packed: bool,
}
impl<Item: Serialize> Encoder<Item>
{
pub fn new() -> Self {
Self {
_data: PhantomData,
sd: SdMode::Never,
packed: false,
}
}
pub fn sd(self, sd: SdMode) -> Self
{
Self { sd, ..self }
}
pub fn packed(self, packed: bool) -> Self {
Self { packed, ..self }
}
}
impl<Item: Serialize> Default for Encoder<Item>
{
fn default() -> Self
{
Self::new()
}
}
struct BytesWriter<'a>(&'a mut BytesMut);
impl Write for BytesWriter<'_>
{
fn write(&mut self, buf: &[u8]) -> IoResult<usize>
{
self.0.extend(buf);
Ok(buf.len())
}
fn flush(&mut self) -> IoResult<()>
{
Ok(())
}
}
impl<Item: Serialize> IoEncoder for Encoder<Item>
{
type Item = Item ;
type Error = Error;
fn encode(&mut self, item: Item, dst: &mut BytesMut) -> Result<(), Error>
{
let writer = BytesWriter(dst);
let mut serializer = if self.packed
{
Serializer::new( IoWrite::new(writer) ).packed_format()
}
else
{
Serializer::new( IoWrite::new(writer) )
};
if self.sd != SdMode::Never
{
serializer.self_describe()?;
}
if self.sd == SdMode::Once
{
self.sd = SdMode::Never;
}
item.serialize( &mut serializer ).map_err( Into::into )
}
}
#[derive(Clone, Debug)]
pub struct Codec<Dec, Enc>
{
dec: Decoder<Dec>,
enc: Encoder<Enc>,
}
impl<'de, Dec: Deserialize<'de>, Enc: Serialize> Codec<Dec, Enc>
{
pub fn new() -> Self
{
Self {
dec: Decoder::new(),
enc: Encoder::new(),
}
}
pub fn sd(self, sd: SdMode) -> Self
{
Self {
dec: self.dec,
enc: Encoder { sd, ..self.enc },
}
}
pub fn packed(self, packed: bool) -> Self
{
Self
{
dec: self.dec,
enc: Encoder { packed, ..self.enc },
}
}
}
impl<'de, Dec: Deserialize<'de>, Enc: Serialize> Default for Codec<Dec, Enc> {
fn default() -> Self {
Self::new()
}
}
impl<'de, Dec: Deserialize<'de>, Enc: Serialize> IoDecoder for Codec<Dec, Enc> {
type Item = Dec;
type Error = Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Dec>, Error> {
self.dec.decode(src)
}
}
impl<'de, Dec: Deserialize<'de>, Enc: Serialize> IoEncoder for Codec<Dec, Enc> {
type Item = Enc;
type Error = Error;
fn encode(&mut self, item: Enc, dst: &mut BytesMut) -> Result<(), Error> {
self.enc.encode(item, dst)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::sync::Arc;
use serde_cbor;
use super::*;
type TestData = HashMap<String, usize>;
fn test_data() -> TestData {
let mut data = HashMap::new();
data.insert("hello".to_owned(), 42usize);
data.insert("world".to_owned(), 0usize);
data
}
fn decode<Dec: IoDecoder<Item = TestData, Error = Error>>(dec: Dec) {
let mut decoder = dec;
let data = test_data();
let encoded = serde_cbor::to_vec(&data).unwrap();
let mut all = BytesMut::with_capacity(128);
all.extend(&encoded);
all.extend(&encoded);
all.extend(&encoded[..1]);
let decoded = decoder.decode(&mut all).unwrap().unwrap();
assert_eq!(data, decoded);
let decoded = decoder.decode(&mut all).unwrap().unwrap();
assert_eq!(data, decoded);
assert_eq!(1, all.len());
assert!(decoder.decode(&mut all).unwrap().is_none());
assert_eq!(1, all.len());
all.extend(&encoded[1..]);
let decoded = decoder.decode(&mut all).unwrap().unwrap();
assert_eq!(data, decoded);
assert!(all.is_empty());
all.extend(&[0, 1, 2, 3, 4]);
decoder.decode(&mut all).unwrap_err();
assert_eq!(5, all.len());
}
#[test]
fn decode_only() {
let decoder = Decoder::new();
decode(decoder);
}
#[test]
fn decode_codec() {
let decoder: Codec<_, ()> = Codec::new();
decode(decoder);
}
fn encode<Enc: IoEncoder<Item = TestData, Error = Error>>(enc: Enc) {
let mut encoder = enc;
let data = test_data();
let mut buffer = BytesMut::with_capacity(0);
encoder.encode(data.clone(), &mut buffer).unwrap();
let pos1 = buffer.len();
let decoded = serde_cbor::from_slice::<TestData>(&buffer).unwrap();
assert_eq!(data, decoded);
encoder.encode(data.clone(), &mut buffer).unwrap();
let pos2 = buffer.len();
assert!(pos2 > pos1);
assert!(pos1 * 2 > pos2);
let decoded = serde_cbor::from_slice::<TestData>(&buffer[pos1..]).unwrap();
assert_eq!(data, decoded);
encoder.encode(data.clone(), &mut buffer).unwrap();
let pos3 = buffer.len();
assert_eq!(pos2 - pos1, pos3 - pos2);
}
#[test]
fn encode_only() {
let encoder = Encoder::new().sd(SdMode::Once);
encode(encoder);
}
#[test]
fn encode_packed() {
let encoder = Encoder::new().packed(true).sd(SdMode::Once);
encode(encoder);
}
#[test]
fn encode_codec() {
let encoder: Codec<(), _> = Codec::new().sd(SdMode::Once);
encode(encoder);
}
#[test]
fn is_send() {
let codec: Codec<(), ()> = Codec::new();
std::thread::spawn(move || {
let _c = codec;
});
}
#[test]
fn is_sync() {
let codec: Arc<Codec<(), ()>> = Arc::new(Codec::new());
std::thread::spawn(move || {
let _c = codec;
});
}
}