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