Skip to content
Snippets Groups Projects
lua.rs 1.80 KiB
use rlua::{Lua, Result as LuaResult, FromLua};
use rocket::{Outcome, http};
use rocket::request::{FromRequest, Request};
use std::convert::{Into, AsRef, AsMut};
use scripting;
use serde::Serialize;
use std::collections::HashMap;

const LIB_JSON_ENCODE: &'static str = include_str!("../scripts/json.lua");

pub struct LuaRuntime(Lua);
impl Into<Lua> for LuaRuntime {
    fn into(self) -> Lua {
        self.0
    }
}
impl AsRef<Lua> for LuaRuntime {
    fn as_ref(&self) -> &Lua {
        &self.0
    }
}
impl AsMut<Lua> for LuaRuntime {
    fn as_mut(&mut self) -> &mut Lua {
        &mut self.0
    }
}

impl <'a, 'req>FromRequest<'a, 'req> for LuaRuntime {
    type Error = ();

    fn from_request(_request: &'a Request<'req>) -> Outcome<Self, (http::Status, ()), ()> {
		match create_runtime(false) {
			Ok(runtime) => Outcome::Success(runtime),
			_ => Outcome::Failure((http::Status::raw(500), ())),
		}
    }
}

pub fn create_runtime(with_debug: bool) -> LuaResult<LuaRuntime> {
    let runtime = if with_debug {
        unsafe { Lua::new_with_debug() }
    } else {
        Lua::new()
    };

	{
		runtime.eval::<()>(LIB_JSON_ENCODE, Some("json.lua".into()))?
	}

	{
		let globals = &runtime.globals();
		let response_constructor = runtime.create_function(|_, (status, content_type, body): (u16, String, String)| {

			let mut headers = HashMap::new();
			headers.insert(String::from("Content-Type"), content_type);

			Ok(scripting::ScriptResponse {
				status,
				headers,
				body: Some(body),
			})
		})?;

		let empty_response_constructor = runtime.create_function(|_, (): ()| {
			Ok(scripting::ScriptResponse {
				status: 204,
				headers: HashMap::new(),
				body: None,
			})
		})?;

		globals.set("response", response_constructor)?;
		globals.set("empty_response", empty_response_constructor)?;
	}

    Ok(LuaRuntime(runtime))
}