Skip to content

Commit ee7ced6

Browse files
committed
Add Chunk::wrap method
1 parent d8307d0 commit ee7ced6

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

src/chunk.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ use std::borrow::Cow;
22
use std::collections::HashMap;
33
use std::ffi::CString;
44
use std::io::Result as IoResult;
5+
use std::marker::PhantomData;
6+
use std::panic::Location;
57
use std::path::{Path, PathBuf};
68
use std::string::String as StdString;
79

810
use crate::error::{Error, Result};
911
use crate::function::Function;
1012
use crate::state::{Lua, WeakLua};
1113
use crate::table::Table;
12-
use crate::traits::{FromLuaMulti, IntoLuaMulti};
14+
use crate::traits::{FromLuaMulti, IntoLua, IntoLuaMulti};
15+
use crate::value::Value;
1316

1417
/// Trait for types [loadable by Lua] and convertible to a [`Chunk`]
1518
///
@@ -561,3 +564,32 @@ impl Chunk<'_> {
561564
buf
562565
}
563566
}
567+
568+
struct WrappedChunk<'a, T: AsChunk<'a>> {
569+
chunk: T,
570+
caller: &'static Location<'static>,
571+
_marker: PhantomData<&'a T>,
572+
}
573+
574+
impl<'a> Chunk<'a> {
575+
/// Wraps a chunk of Lua code, returning an opaque type that implements [`IntoLua`] trait.
576+
///
577+
/// The resulted `IntoLua` implementation will convert the chunk into a Lua function without
578+
/// executing it.
579+
#[track_caller]
580+
pub fn wrap(chunk: impl AsChunk<'a> + 'a) -> impl IntoLua + 'a {
581+
WrappedChunk {
582+
chunk,
583+
caller: Location::caller(),
584+
_marker: PhantomData,
585+
}
586+
}
587+
}
588+
589+
impl<'a, T: AsChunk<'a>> IntoLua for WrappedChunk<'a, T> {
590+
fn into_lua(self, lua: &Lua) -> Result<Value> {
591+
lua.load_with_location(self.chunk, self.caller)
592+
.into_function()
593+
.map(Value::Function)
594+
}
595+
}

src/state.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,10 +1003,17 @@ impl Lua {
10031003
/// [`Chunk::exec`]: crate::Chunk::exec
10041004
#[track_caller]
10051005
pub fn load<'a>(&self, chunk: impl AsChunk<'a>) -> Chunk<'a> {
1006-
let caller = Location::caller();
1006+
self.load_with_location(chunk, Location::caller())
1007+
}
1008+
1009+
pub(crate) fn load_with_location<'a>(
1010+
&self,
1011+
chunk: impl AsChunk<'a>,
1012+
location: &'static Location<'static>,
1013+
) -> Chunk<'a> {
10071014
Chunk {
10081015
lua: self.weak(),
1009-
name: chunk.name().unwrap_or_else(|| caller.to_string()),
1016+
name: chunk.name().unwrap_or_else(|| location.to_string()),
10101017
env: chunk.environment(self),
10111018
mode: chunk.mode(),
10121019
source: chunk.source(),

tests/chunk.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{fs, io};
22

3-
use mlua::{Lua, Result};
3+
use mlua::{Chunk, Lua, Result};
44

55
#[test]
66
fn test_chunk_path() -> Result<()> {
@@ -121,3 +121,20 @@ fn test_compiler() -> Result<()> {
121121

122122
Ok(())
123123
}
124+
125+
#[test]
126+
fn test_chunk_wrap() -> Result<()> {
127+
let lua = Lua::new();
128+
129+
let f = Chunk::wrap("return 123");
130+
lua.globals().set("f", f)?;
131+
lua.load("assert(f() == 123)").exec().unwrap();
132+
133+
lua.globals().set("f2", Chunk::wrap("c()"))?;
134+
assert!(
135+
(lua.load("f2()").exec().err().unwrap().to_string()).contains(file!()),
136+
"wrong chunk location"
137+
);
138+
139+
Ok(())
140+
}

0 commit comments

Comments
 (0)