use std::fmt::{self, Debug, Display, Formatter};
use super::{Scribe, try_set_header};
use crate::http::Response;
use crate::http::header::{CONTENT_TYPE, HeaderValue};
#[non_exhaustive]
pub enum Text<C> {
Plain(C),
Json(C),
Xml(C),
Html(C),
Js(C),
Css(C),
Csv(C),
Atom(C),
Rss(C),
Rdf(C),
}
impl<C> Text<C>
where
C: AsRef<str>,
{
fn try_set_header(self, res: &mut Response) -> C {
let (ctype, content) = match self {
Self::Plain(content) => (
HeaderValue::from_static("text/plain; charset=utf-8"),
content,
),
Self::Json(content) => (
HeaderValue::from_static("application/json; charset=utf-8"),
content,
),
Self::Xml(content) => (
HeaderValue::from_static("application/xml; charset=utf-8"),
content,
),
Self::Html(content) => (
HeaderValue::from_static("text/html; charset=utf-8"),
content,
),
Self::Js(content) => (
HeaderValue::from_static("text/javascript; charset=utf-8"),
content,
),
Self::Css(content) => (HeaderValue::from_static("text/css; charset=utf-8"), content),
Self::Csv(content) => (HeaderValue::from_static("text/csv; charset=utf-8"), content),
Self::Atom(content) => (
HeaderValue::from_static("application/atom+xml; charset=utf-8"),
content,
),
Self::Rss(content) => (
HeaderValue::from_static("application/rss+xml; charset=utf-8"),
content,
),
Self::Rdf(content) => (
HeaderValue::from_static("application/rdf+xml; charset=utf-8"),
content,
),
};
try_set_header(&mut res.headers, CONTENT_TYPE, ctype);
content
}
}
impl Scribe for Text<&'static str> {
#[inline]
fn render(self, res: &mut Response) {
let content = self.try_set_header(res);
let _ = res.write_body(content);
}
}
impl Scribe for Text<String> {
#[inline]
fn render(self, res: &mut Response) {
let content = self.try_set_header(res);
let _ = res.write_body(content);
}
}
impl Scribe for Text<&String> {
#[inline]
fn render(self, res: &mut Response) {
let content = self.try_set_header(res);
let _ = res.write_body(content.as_bytes().to_vec());
}
}
impl<C: Debug> Debug for Text<C> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Plain(content) => f.debug_tuple("Text::Plain").field(content).finish(),
Self::Json(content) => f.debug_tuple("Text::Json").field(content).finish(),
Self::Xml(content) => f.debug_tuple("Text::Xml").field(content).finish(),
Self::Html(content) => f.debug_tuple("Text::Html").field(content).finish(),
Self::Js(content) => f.debug_tuple("Text::Js").field(content).finish(),
Self::Css(content) => f.debug_tuple("Text::Css").field(content).finish(),
Self::Csv(content) => f.debug_tuple("Text::Csv").field(content).finish(),
Self::Atom(content) => f.debug_tuple("Text::Atom").field(content).finish(),
Self::Rss(content) => f.debug_tuple("Text::Rss").field(content).finish(),
Self::Rdf(content) => f.debug_tuple("Text::Rdf").field(content).finish(),
}
}
}
impl<C: Display> Display for Text<C> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Plain(content)
| Self::Json(content)
| Self::Xml(content)
| Self::Html(content)
| Self::Js(content)
| Self::Css(content)
| Self::Csv(content)
| Self::Atom(content)
| Self::Rss(content)
| Self::Rdf(content) => Display::fmt(content, f),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::*;
use crate::test::{ResponseExt, TestClient};
#[tokio::test]
async fn test_write_str() {
#[handler]
async fn test() -> &'static str {
"hello"
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "hello");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/plain; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_string() {
#[handler]
async fn test() -> String {
"hello".to_owned()
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "hello");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/plain; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_plain_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Plain("hello")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "hello");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/plain; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_json_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Json(r#"{"hello": "world"}"#)
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), r#"{"hello": "world"}"#);
assert_eq!(
res.headers().get("content-type").unwrap(),
"application/json; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_html_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Html("<html><body>hello</body></html>")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(
res.take_string().await.unwrap(),
"<html><body>hello</body></html>"
);
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/html; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_xml_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Xml("<xml>hello</xml>")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "<xml>hello</xml>");
assert_eq!(
res.headers().get("content-type").unwrap(),
"application/xml; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_js_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Js("var a = 1;")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "var a = 1;");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/javascript; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_css_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Css("body {color: red;}")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "body {color: red;}");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/css; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_csv_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Csv("a,b,c")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "a,b,c");
assert_eq!(
res.headers().get("content-type").unwrap(),
"text/csv; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_atom_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Atom("<feed></feed>")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "<feed></feed>");
assert_eq!(
res.headers().get("content-type").unwrap(),
"application/atom+xml; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_rss_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Rss("<rss></rss>")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "<rss></rss>");
assert_eq!(
res.headers().get("content-type").unwrap(),
"application/rss+xml; charset=utf-8"
);
}
#[tokio::test]
async fn test_write_rdf_text() {
#[handler]
async fn test() -> Text<&'static str> {
Text::Rdf("<rdf></rdf>")
}
let router = Router::new().push(Router::with_path("test").get(test));
let mut res = TestClient::get("http://127.0.0.1:8698/test")
.send(router)
.await;
assert_eq!(res.take_string().await.unwrap(), "<rdf></rdf>");
assert_eq!(
res.headers().get("content-type").unwrap(),
"application/rdf+xml; charset=utf-8"
);
}
}