1#![forbid(unsafe_code)]
2#![deny(rust_2018_idioms, nonstandard_style)]
3#![warn(future_incompatible)]
4
5pub mod config;
6pub mod error;
7
8#[cfg(feature = "serde")]
9mod serde_compat;
10#[cfg(feature = "serde")]
11pub use serde_compat::BincodeSerde;
12
13use config::{BincodeConfig, DEFAULT_LIMIT_BYTES};
14
15use std::{ops::Deref, pin::Pin};
16
17use actix_web::{dev::Payload, web::BytesMut, FromRequest, HttpMessage, HttpRequest};
18use bincode::config::Configuration;
19use futures::{Future, StreamExt};
20
21pub struct Bincode<T>(T);
39
40impl<T> FromRequest for Bincode<T>
42where
43 T: bincode::Decode<()>, {
45 type Error = error::BincodePayloadError;
46 type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
47
48 fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
49 if req.content_type() != "application/octet-stream" {
51 let content_type = req.content_type().to_string();
52 return Box::pin(async { Err(error::BincodePayloadError::ContentType(content_type)) });
53 }
54
55 let config = req
57 .app_data::<BincodeConfig>()
58 .map_or(BincodeConfig::default(), |c| *c);
59
60 let bincode_config = req
62 .app_data::<Configuration>()
63 .map_or(bincode::config::standard(), |c| *c);
64
65 let mut payload = payload.take();
66
67 Box::pin(async move {
68 let mut buffer: BytesMut = BytesMut::with_capacity(config.buf_size);
69
70 while let Some(bytes) = payload.next().await {
71 let bytes = bytes?;
72
73 if buffer.len() + bytes.len() > config.limit {
75 return Err(error::BincodePayloadError::Overflow(config.limit));
76 }
77
78 buffer.extend(bytes);
79 }
80
81 match bincode::decode_from_slice::<T, _>(&buffer, bincode_config) {
82 Ok((obj, _)) => Ok(Bincode(obj)),
83 Err(e) => Err(error::BincodePayloadError::Decode(e)),
84 }
85 })
86 }
87}
88
89impl<T: bincode::Encode> Bincode<T> {
90 pub fn into_inner(self) -> T {
92 self.0
93 }
94
95 #[allow(clippy::missing_errors_doc)]
97 pub fn into_bytes(
98 self,
99 config: Option<Configuration>,
100 ) -> Result<BytesMut, error::BincodePayloadError> {
101 let mut bytes = BytesMut::with_capacity(DEFAULT_LIMIT_BYTES);
102 let ser = bincode::encode_to_vec(
103 self.into_inner(),
104 config.unwrap_or(bincode::config::standard()),
105 )?;
106 bytes.extend(ser);
107 Ok(bytes)
108 }
109}
110
111impl<T> Deref for Bincode<T> {
113 type Target = T;
114 fn deref(&self) -> &Self::Target {
115 &self.0
116 }
117}