use encoding::{Encoding, all::ISO_8859_1};
use crate::{AriosError, AriosResult};
pub struct AriosResponse {
pub protocol: String,
pub status: String,
pub code: u16,
pub content_type: Option<String>,
pub charset: Option<String>,
pub content_length: Option<usize>,
pub header: String,
pub raw_body: Vec<u8>,
}
impl AriosResponse {
pub fn bytes(&self) -> &[u8] {
&self.raw_body
}
pub fn text(&self) -> AriosResult<String> {
match self
.charset
.as_deref()
.unwrap_or("utf-8")
.to_lowercase()
.as_str()
{
"iso-8859-1" => ISO_8859_1
.decode(&self.raw_body, encoding::DecoderTrap::Replace)
.map_err(|_| AriosError::InvalidResponse("invalid response body encoding")),
_ => Ok(String::from_utf8_lossy(&self.raw_body).to_string()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn response_with_body(raw_body: Vec<u8>, charset: Option<&str>) -> AriosResponse {
AriosResponse {
protocol: String::from("HTTP/1.1"),
status: String::from("OK"),
code: 200,
content_type: Some(String::from("text/plain")),
charset: charset.map(String::from),
content_length: Some(raw_body.len()),
header: String::from("HTTP/1.1 200 OK\r\n"),
raw_body,
}
}
#[test]
fn bytes_returns_raw_body_slice() {
let response = response_with_body(vec![0x41, 0x42, 0x43], None);
assert_eq!(response.bytes(), &[0x41, 0x42, 0x43]);
}
#[test]
fn text_decodes_utf8_by_default() {
let response = response_with_body("Olá".as_bytes().to_vec(), None);
let text = response.text().unwrap();
assert_eq!(text, "Olá");
}
#[test]
fn text_decodes_iso_8859_1_when_charset_is_set() {
let response = response_with_body(vec![0x4F, 0x6C, 0xE1], Some("iso-8859-1"));
let text = response.text().unwrap();
assert_eq!(text, "Olá");
}
#[test]
fn text_treats_charset_case_insensitively() {
let response = response_with_body(vec![0x4F, 0x6C, 0xE1], Some("ISO-8859-1"));
let text = response.text().unwrap();
assert_eq!(text, "Olá");
}
}