ferron/util/
fcgi_name_value_pair.rs

1/// Constructs a FastCGI name-value pair
2pub fn construct_fastcgi_name_value_pair(name: &[u8], value: &[u8]) -> Vec<u8> {
3  // Name and value lengths (for determining the vector allocation size)
4  let name_length = name.len();
5  let value_length = value.len();
6
7  // Allocate the vector with the preallocated capacity
8  let mut name_value_pair = Vec::with_capacity(
9    if name_length < 128 { 1 } else { 4 }
10      + if value_length < 128 { 1 } else { 4 }
11      + name_length
12      + value_length,
13  );
14
15  // Name length
16  if name_length < 128 {
17    name_value_pair.extend_from_slice(&(name_length as u8).to_be_bytes());
18  } else {
19    name_value_pair.extend_from_slice(&((name_length as u32) | 0x80000000).to_be_bytes());
20  }
21
22  // Value length
23  if value_length < 128 {
24    name_value_pair.extend_from_slice(&(value_length as u8).to_be_bytes());
25  } else {
26    name_value_pair.extend_from_slice(&((value_length as u32) | 0x80000000).to_be_bytes());
27  }
28
29  // Name
30  name_value_pair.extend_from_slice(name);
31
32  // Value
33  name_value_pair.extend_from_slice(value);
34
35  name_value_pair
36}
37
38#[cfg(test)]
39mod tests {
40  use super::*;
41
42  #[test]
43  fn test_short_name_and_value() {
44    let name = b"HOST";
45    let value = b"localhost";
46    let expected = vec![
47      0x04, // Name length (4 bytes)
48      0x09, // Value length (9 bytes)
49      b'H', b'O', b'S', b'T', // Name
50      b'l', b'o', b'c', b'a', b'l', b'h', b'o', b's', b't', // Value
51    ];
52    assert_eq!(construct_fastcgi_name_value_pair(name, value), expected);
53  }
54
55  #[test]
56  fn test_long_name_and_value() {
57    let name = vec![b'N'; 130]; // Name length 130
58    let value = vec![b'V'; 135]; // Value length 135
59    let mut expected = vec![
60      0x80, 0x00, 0x00, 0x82, // Name length (130 bytes)
61      0x80, 0x00, 0x00, 0x87, // Value length (135 bytes)
62    ];
63    expected.extend_from_slice(&name);
64    expected.extend_from_slice(&value);
65    assert_eq!(construct_fastcgi_name_value_pair(&name, &value), expected);
66  }
67
68  #[test]
69  fn test_empty_name_and_value() {
70    let name = b"";
71    let value = b"";
72    let expected = vec![
73      0x00, // Name length (0 bytes)
74      0x00, // Value length (0 bytes)
75    ];
76    assert_eq!(construct_fastcgi_name_value_pair(name, value), expected);
77  }
78
79  #[test]
80  fn test_name_length_127() {
81    let name = vec![b'a'; 127];
82    let value = b"value";
83    let mut expected = vec![
84      0x7f, // Name length (127 bytes)
85      0x05, // Value length (5 bytes)
86    ];
87    expected.extend_from_slice(&name);
88    expected.extend_from_slice(value);
89    assert_eq!(construct_fastcgi_name_value_pair(&name, value), expected);
90  }
91
92  #[test]
93  fn test_value_length_127() {
94    let name = b"name";
95    let value = vec![b'b'; 127];
96    let mut expected = vec![
97      0x04, // Name length (4 bytes)
98      0x7f, // Value length (127 bytes)
99    ];
100    expected.extend_from_slice(name);
101    expected.extend_from_slice(&value);
102    assert_eq!(construct_fastcgi_name_value_pair(name, &value), expected);
103  }
104}