ferron/util/
fcgi_encoder.rs1use tokio_util::bytes::{BufMut, BytesMut};
2use tokio_util::codec::Encoder;
3
4use crate::ferron_util::fcgi_record::construct_fastcgi_record;
5
6pub struct FcgiEncoder;
7
8impl FcgiEncoder {
9 pub fn new() -> Self {
10 Self
11 }
12}
13
14impl Encoder<&[u8]> for FcgiEncoder {
15 type Error = std::io::Error;
16
17 fn encode(&mut self, item: &[u8], dst: &mut BytesMut) -> Result<(), Self::Error> {
18 let mut offset = 0;
19 let mut first_written = false;
20 while offset < item.len() || (item.is_empty() && !first_written) {
21 let chunk_size = std::cmp::min(65535, item.len() - offset);
22 let chunk = &item[offset..offset + chunk_size];
23
24 let record = construct_fastcgi_record(5, 1, chunk);
26 dst.put(record.as_slice());
27
28 first_written = true;
29 offset += chunk_size;
30 }
31
32 Ok(())
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use tokio_util::codec::Encoder;
40
41 #[test]
42 fn test_fcgi_encoder() {
43 let mut encoder = FcgiEncoder::new();
44 let mut dst = BytesMut::new();
45 let item = b"Test data";
46
47 encoder.encode(item, &mut dst).unwrap();
48
49 let expected_record = vec![
51 1, 5, 0, 1, 0, 9, 7, 0, 84, 101, 115, 116, 32, 100, 97, 116, 97, 0, 0, 0, 0, 0, 0, 0, ];
61
62 assert_eq!(dst.to_vec(), expected_record);
63 }
64}