use std::{collections::HashMap, str::FromStr}; use mlua::{FromLua, Lua, Value}; use crate::{ handler::{self, Handle}, request::Request, response::{Body, Response, Status}, }; #[derive(Debug, Clone)] pub struct LuaResponse { content: Option>, status: Status, headers: HashMap>, } impl Handle for LuaResponse { async fn handle(self, _: Request) -> Result { Ok(Response::builder() .status(self.status) .headers(self.headers) .body(match self.content { Some(content) => Body::Buffer(content), None => Body::Empty, })) } } impl FromLua for LuaResponse { fn from_lua(value: Value, _: &Lua) -> mlua::Result { match value { Value::Table(table) => { let content = match table.get("content")? { Value::String(string) => Some(string.as_bytes().to_vec()), _ => None, }; let status = match table.get("status")? { Value::String(string) => Status::from_str(&string.to_str()?).map_err(|e| { mlua::Error::RuntimeError(format!( "failed to parse status from string: {e}" )) })?, Value::Integer(i) => Status::from_repr(i as usize).ok_or_else(|| { mlua::Error::runtime(format!("failed to parse status from integer: {i}")) })?, _ => return Err(mlua::Error::runtime("invalid type when reading status")), }; let headers: HashMap> = match table.get::("headers")? { Value::Table(table) => { let mut hashmap = HashMap::>::new(); for result in table.pairs() { let (key, value): (String, mlua::BString) = result?; hashmap.insert(key, value.to_vec()); } hashmap } _ => HashMap::new(), }; Ok(Self { content, status, headers, }) } _ => Err(mlua::Error::runtime("expected table")), } } }