1use std::convert::Infallible;
2use std::str::FromStr;
3
4use crate::hist::{self, Body, Encoding};
5
6pub trait ToLines {
8 type Error: std::error::Error;
10
11 fn to_lines(&self) -> Result<Vec<String>, Self::Error>;
13}
14
15impl ToLines for hyper::Request<Vec<u8>> {
16 type Error = crate::Error;
17
18 fn to_lines(&self) -> Result<Vec<String>, Self::Error> {
19 let mut res = Vec::new();
20
21 let mut status = String::new();
22
23 status.push_str(self.method().to_string().as_ref());
24 status.push(' ');
25 status.push_str(self.uri().path());
26 if let Some(s) = self.uri().query() {
27 status.push('?');
28 status.push_str(s);
29 }
30
31 res.push(status);
32
33 for (k, v) in self.headers() {
34 res.push(format!("{}: {}", k, v.to_str()?));
35 }
36
37 res.push(String::new());
38
39 let body = std::str::from_utf8(self.body())?;
40
41 for line in body.lines() {
42 res.push(line.to_string());
43 }
44
45 Ok(res)
46 }
47}
48
49impl ToLines for hist::Request {
50 type Error = Infallible;
51
52 fn to_lines(&self) -> Result<Vec<String>, Self::Error> {
53 let mut res = Vec::new();
54 let mut status = String::new();
55
56 status.push_str(&self.method);
57 status.push(' ');
58 status.push_str(&self.path);
59
60 let mut query = String::new();
61 for (k, v) in &self.query {
62 if !query.is_empty() {
63 query.push('&');
64 }
65
66 query.push_str(k);
67 query.push('=');
68 query.push_str(v);
69 }
70
71 if !query.is_empty() {
72 status.push('?');
73 status.push_str(&query);
74 }
75
76 res.push(status);
77
78 let mut encoding = Encoding::Bare;
79
80 for (k, v) in &self.headers {
81 if k == "content-encoding" {
82 if let Ok(e) = Encoding::from_str(v) {
83 encoding = e;
84 }
85 }
86 res.push(format!("{}: {}", k, v));
87 }
88
89 res.push(String::new());
90
91 let b: Body;
92
93 let body = if let Ok(body) = self.body.decode(encoding) {
94 b = body;
95 &b
96 } else {
97 &self.body
98 };
99
100 if let Some(lines) = body.lines() {
101 for line in lines {
102 res.push(line.to_string());
103 }
104 } else {
105 res.push("[binary]".to_string());
106 body.hex(&mut res);
107 }
108
109 Ok(res)
110 }
111}
112
113impl ToLines for hyper::Response<Vec<u8>> {
114 type Error = crate::Error;
115
116 fn to_lines(&self) -> Result<Vec<String>, Self::Error> {
117 let mut res = Vec::new();
118
119 res.push(self.status().as_u16().to_string());
120
121 for (k, v) in self.headers() {
122 res.push(format!("{}: {}", k, v.to_str()?));
123 }
124
125 res.push(String::new());
126
127 let body = std::str::from_utf8(self.body())?;
128
129 for line in body.lines() {
130 res.push(line.to_string());
131 }
132
133 Ok(res)
134 }
135}
136impl ToLines for crate::hist::Response {
137 type Error = Infallible;
138
139 fn to_lines(&self) -> Result<Vec<String>, Self::Error> {
140 let mut res = Vec::new();
141
142 res.push(self.status.to_string());
143
144 let mut encoding = Encoding::Bare;
145
146 for (k, v) in &self.headers {
147 if k == "content-encoding" {
148 if let Ok(e) = Encoding::from_str(v) {
149 encoding = e;
150 }
151 }
152 res.push(format!("{}: {}", k, v));
153 }
154
155 res.push(String::new());
156 let b: Body;
157
158 let body = if let Ok(body) = self.body.decode(encoding) {
159 b = body;
160 &b
161 } else {
162 &self.body
163 };
164
165 if let Some(lines) = body.lines() {
166 for line in lines {
167 res.push(line.to_string());
168 }
169 } else {
170 res.push("[binary]".to_string());
171 body.hex(&mut res);
172 }
173
174 Ok(res)
175 }
176}