prax/lines/
to_lines.rs

1use std::convert::Infallible;
2use std::str::FromStr;
3
4use crate::hist::{self, Body, Encoding};
5
6/// Generates a representation line by line
7pub trait ToLines {
8    /// Error associated with generating line by line representation
9    type Error: std::error::Error;
10
11    /// generate a line by line text representation
12    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}