1use std::fmt;
4use std::io::{self, Write};
5
6use percent_encoding::AsciiSet;
7
8pub struct BytesWriter {
12 buf: bytes::BytesMut,
13}
14
15impl BytesWriter {
16 #[inline]
17 pub fn with_capacity(capacity: usize) -> Self {
19 Self {
20 buf: bytes::BytesMut::with_capacity(capacity)
21 }
22 }
23
24 #[inline]
25 pub fn freeze(self) -> bytes::Bytes {
27 self.buf.freeze()
28 }
29}
30
31impl Default for BytesWriter {
32 fn default() -> Self {
33 Self::with_capacity(0)
34 }
35}
36
37impl Into<bytes::Bytes> for BytesWriter {
38 #[inline]
39 fn into(self) -> bytes::Bytes {
40 self.freeze()
41 }
42}
43
44impl io::Write for BytesWriter {
45 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
46 self.buf.extend_from_slice(buf);
47 Ok(buf.len())
48 }
49
50 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
51 self.buf.extend_from_slice(buf);
52 Ok(())
53 }
54
55 fn flush(&mut self) -> io::Result<()> {
56 Ok(())
57 }
58}
59
60impl fmt::Write for BytesWriter {
61 fn write_str(&mut self, text: &str) -> fmt::Result {
62 self.buf.extend_from_slice(text.as_bytes());
63 Ok(())
64 }
65}
66
67pub fn display_to_header<T: fmt::Display>(data: &T) -> http::header::HeaderValue {
69 let mut res = BytesWriter::default();
70 let _ = write!(&mut res, "{}", data);
71 unsafe { http::header::HeaderValue::from_maybe_shared_unchecked(res.freeze()) }
72}
73
74pub const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS.add(b' ').add(b'"').add(b'<').add(b'>').add(b'`');
76
77pub const PATH_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'#').add(b'?').add(b'{').add(b'}');
79
80pub const USER_INFO_ENCODE_SET: &AsciiSet = &PATH_ENCODE_SET.add(b'/').add(b':').add(b';').add(b'=').add(b'@').add(b'[').add(b'\\').add(b']').add(b'^').add(b'|');
82
83pub const HEADER_VALUE_ENCODE_SET: &AsciiSet = &percent_encoding::NON_ALPHANUMERIC.remove(b'!').remove(b'#').remove(b'$').remove(b'&').remove(b'+').remove(b'-').remove(b'.').remove(b'^').remove(b'_').remove(b'`').remove(b'|').remove(b'~');