Skip to content

Commit

Permalink
Add Chunk::wrap method
Browse files Browse the repository at this point in the history
  • Loading branch information
khvzak committed Nov 22, 2024
1 parent d8307d0 commit ee7ced6
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
34 changes: 33 additions & 1 deletion src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ use std::borrow::Cow;
use std::collections::HashMap;
use std::ffi::CString;
use std::io::Result as IoResult;
use std::marker::PhantomData;
use std::panic::Location;
use std::path::{Path, PathBuf};
use std::string::String as StdString;

use crate::error::{Error, Result};
use crate::function::Function;
use crate::state::{Lua, WeakLua};
use crate::table::Table;
use crate::traits::{FromLuaMulti, IntoLuaMulti};
use crate::traits::{FromLuaMulti, IntoLua, IntoLuaMulti};
use crate::value::Value;

/// Trait for types [loadable by Lua] and convertible to a [`Chunk`]
///
Expand Down Expand Up @@ -561,3 +564,32 @@ impl Chunk<'_> {
buf
}
}

struct WrappedChunk<'a, T: AsChunk<'a>> {
chunk: T,
caller: &'static Location<'static>,
_marker: PhantomData<&'a T>,
}

impl<'a> Chunk<'a> {
/// Wraps a chunk of Lua code, returning an opaque type that implements [`IntoLua`] trait.
///
/// The resulted `IntoLua` implementation will convert the chunk into a Lua function without
/// executing it.
#[track_caller]
pub fn wrap(chunk: impl AsChunk<'a> + 'a) -> impl IntoLua + 'a {
WrappedChunk {
chunk,
caller: Location::caller(),
_marker: PhantomData,
}
}
}

impl<'a, T: AsChunk<'a>> IntoLua for WrappedChunk<'a, T> {
fn into_lua(self, lua: &Lua) -> Result<Value> {
lua.load_with_location(self.chunk, self.caller)
.into_function()
.map(Value::Function)
}
}
11 changes: 9 additions & 2 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,10 +1003,17 @@ impl Lua {
/// [`Chunk::exec`]: crate::Chunk::exec
#[track_caller]
pub fn load<'a>(&self, chunk: impl AsChunk<'a>) -> Chunk<'a> {
let caller = Location::caller();
self.load_with_location(chunk, Location::caller())
}

pub(crate) fn load_with_location<'a>(
&self,
chunk: impl AsChunk<'a>,
location: &'static Location<'static>,
) -> Chunk<'a> {
Chunk {
lua: self.weak(),
name: chunk.name().unwrap_or_else(|| caller.to_string()),
name: chunk.name().unwrap_or_else(|| location.to_string()),
env: chunk.environment(self),
mode: chunk.mode(),
source: chunk.source(),
Expand Down
19 changes: 18 additions & 1 deletion tests/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs, io};

use mlua::{Lua, Result};
use mlua::{Chunk, Lua, Result};

#[test]
fn test_chunk_path() -> Result<()> {
Expand Down Expand Up @@ -121,3 +121,20 @@ fn test_compiler() -> Result<()> {

Ok(())
}

#[test]
fn test_chunk_wrap() -> Result<()> {
let lua = Lua::new();

let f = Chunk::wrap("return 123");
lua.globals().set("f", f)?;
lua.load("assert(f() == 123)").exec().unwrap();

lua.globals().set("f2", Chunk::wrap("c()"))?;
assert!(
(lua.load("f2()").exec().err().unwrap().to_string()).contains(file!()),
"wrong chunk location"
);

Ok(())
}

0 comments on commit ee7ced6

Please sign in to comment.