Skip to content
This repository was archived by the owner on Aug 15, 2021. It is now read-only.

Commit 57ce61e

Browse files
committed
Add tokio_util::codec::{Encoder, Decoder} support
This allows CBOR to operate as an underlying frame.
1 parent a218403 commit 57ce61e

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ maintenance = { status = "passively-maintained" }
1919
[dependencies]
2020
half = "1.2.0"
2121
serde = { version = "1.0.14", default-features = false }
22+
tokio-util = { version = "0.3", optional = true }
23+
bytes = { version = "0.5", optional = true }
2224

2325
[dev-dependencies]
2426
serde_derive = { version = "1.0.14", default-features = false }
@@ -31,3 +33,4 @@ alloc = ["serde/alloc"]
3133
std = ["serde/std" ]
3234
unsealed_read_write = []
3335
tags = []
36+
codec = ["tokio-util/codec", "bytes"]

src/codec.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! Encoding and decoding for tokio
2+
3+
use crate::error::Category;
4+
use crate::Error;
5+
6+
use std::marker::PhantomData;
7+
8+
use bytes::{buf::ext::BufMutExt, buf::Buf, BytesMut};
9+
use serde::de::DeserializeOwned;
10+
use serde::Serialize;
11+
use tokio_util::codec;
12+
13+
/// A `tokio_util::codec::Encoder` for CBOR frames
14+
pub struct Encoder<T: Serialize>(PhantomData<T>);
15+
16+
impl<T: Serialize> Default for Encoder<T> {
17+
fn default() -> Self {
18+
Self(PhantomData)
19+
}
20+
}
21+
22+
impl<T: Serialize> codec::Encoder<&T> for Encoder<T> {
23+
type Error = Error;
24+
25+
fn encode(&mut self, item: &T, dst: &mut BytesMut) -> Result<(), Error> {
26+
crate::to_writer(dst.writer(), item)
27+
}
28+
}
29+
30+
/// A `tokio_util::codec::Decoder` for CBOR frames
31+
pub struct Decoder<T: DeserializeOwned>(PhantomData<T>);
32+
33+
impl<T: DeserializeOwned> Default for Decoder<T> {
34+
fn default() -> Self {
35+
Self(PhantomData)
36+
}
37+
}
38+
39+
impl<T: DeserializeOwned> codec::Decoder for Decoder<T> {
40+
type Item = T;
41+
type Error = Error;
42+
43+
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
44+
let mut bytes: &[u8] = src.as_ref();
45+
let starting = bytes.len();
46+
47+
let item: T = match crate::from_reader(&mut bytes) {
48+
Err(e) if e.classify() == Category::Eof => return Ok(None),
49+
Ok(v) => v,
50+
e => e?,
51+
};
52+
53+
let ending = bytes.len();
54+
src.advance(starting - ending);
55+
Ok(Some(item))
56+
}
57+
}
58+
59+
/// A Codec for CBOR frames
60+
#[derive(Default)]
61+
pub struct Codec<T: Serialize, U: DeserializeOwned>(Encoder<T>, Decoder<U>);
62+
63+
impl<T: Serialize, U: DeserializeOwned> codec::Encoder<&T> for Codec<T, U> {
64+
type Error = Error;
65+
66+
#[inline]
67+
fn encode(&mut self, item: &T, dst: &mut BytesMut) -> Result<(), Error> {
68+
self.0.encode(item, dst)
69+
}
70+
}
71+
72+
impl<T: Serialize, U: DeserializeOwned> codec::Decoder for Codec<T, U> {
73+
type Item = U;
74+
type Error = Error;
75+
76+
#[inline]
77+
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
78+
self.1.decode(src)
79+
}
80+
}

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ mod write;
335335
#[cfg(feature = "std")]
336336
pub mod value;
337337

338+
#[cfg(feature = "codec")]
339+
pub mod codec;
340+
338341
// Re-export the [items recommended by serde](https://serde.rs/conventions.html).
339342
#[doc(inline)]
340343
pub use crate::de::{Deserializer, StreamDeserializer};

tests/codec.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#![cfg(feature = "codec")]
2+
3+
use bytes::{BufMut, BytesMut};
4+
use serde_cbor::{codec::Codec, error::Category};
5+
use tokio_util::codec::{Decoder, Encoder};
6+
7+
#[test]
8+
fn decode() {
9+
let mut codec = Codec::<u8, u8>::default();
10+
11+
assert_eq!(
12+
codec
13+
.decode(&mut b"\xFF"[..].into())
14+
.err()
15+
.unwrap()
16+
.classify(),
17+
Category::Syntax
18+
);
19+
20+
assert_eq!(
21+
codec
22+
.decode(&mut b"\x24"[..].into())
23+
.err()
24+
.unwrap()
25+
.classify(),
26+
Category::Data
27+
);
28+
29+
assert_eq!(codec.decode(&mut b"\x07"[..].into()).unwrap().unwrap(), 7);
30+
31+
let mut buf = BytesMut::with_capacity(2);
32+
assert_eq!(codec.decode(&mut buf).unwrap(), None);
33+
buf.put_u8(0x18);
34+
assert_eq!(codec.decode(&mut buf).unwrap(), None);
35+
buf.put_u8(0x18);
36+
assert_eq!(codec.decode(&mut buf).unwrap(), Some(24));
37+
}
38+
39+
#[test]
40+
fn encode() {
41+
let mut codec = Codec::<u8, u8>::default();
42+
let mut buf = BytesMut::new();
43+
44+
codec.encode(&7, &mut buf).unwrap();
45+
assert_eq!(buf.len(), 1);
46+
assert_eq!(buf[0], 7);
47+
}

0 commit comments

Comments
 (0)