mod builder; use get::Get; use std::collections::HashMap; use tokio::{ fs::File, io::{self, AsyncWrite, AsyncWriteExt}, }; use strum::{Display, EnumString, FromRepr}; use builder::Builder; #[allow(unreachable_patterns)] #[derive(Debug, Clone, Copy, Display, EnumString, FromRepr)] pub enum Status { #[strum(to_string = "200 OK", serialize = "OK")] Ok = 200, #[strum(to_string = "404 Not Found", serialize = "Not Found")] NotFound = 404, #[strum( to_string = "500 Internal Server Error", serialize = "Internal ServerError" )] InternalServerError = 500, } #[derive(Debug)] pub enum Body { File(File), Buffer(Vec), Empty, } #[derive(Debug, Get)] pub struct Response { status: Status, headers: HashMap>, body: Body, } impl Response { pub fn builder() -> Builder { Builder::new() } } impl Response { pub async fn serialize( mut self, mut writer: W, ) -> Result<(), io::Error> { writer.write_all(b"HTTP/1.1 ").await?; writer.write_all(self.status.to_string().as_bytes()).await?; writer.write_all(b"\r\n").await?; for (key, value) in &self.headers { writer.write_all(key.as_bytes()).await?; writer.write_all(b": ").await?; writer.write_all(value).await?; writer.write_all(b"\r\n").await?; } writer.write_all(b"\r\n").await?; match &mut self.body { Body::File(file) => { io::copy(file, &mut writer).await?; } Body::Buffer(buf) => { writer.write_all(buf).await?; } Body::Empty => (), } Ok(()) } }