Skip to content

Commit

Permalink
feat: add parse_spanned function (#32)
Browse files Browse the repository at this point in the history
* feat: add `parse_spanned` function

* chore: make clippy happy
  • Loading branch information
vhyrro authored Jun 27, 2024
1 parent 086f847 commit 632a479
Showing 1 changed file with 117 additions and 17 deletions.
134 changes: 117 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use mlua::{ExternalError, Lua, LuaSerdeExt, Result};
use mlua::{ExternalError, Lua, LuaSerdeExt, Result, Value};
use std::cell::RefCell;
use std::rc::Rc;
use toml_edit::DocumentMut;
use toml_edit::{DocumentMut, ImDocument, Key};

// TODO: Better error messages

Expand Down Expand Up @@ -50,7 +50,7 @@ where
table.set("__path", path)?;
table.set_metatable(Some(mt_clone.clone()));

Ok(mlua::Value::Table(table))
Ok(Value::Table(table))
}
toml_edit::Item::Value(value) => match value {
toml_edit::Value::String(str) => lua.to_value(&str.value()),
Expand All @@ -61,15 +61,15 @@ where
let table = lua.create_table()?;
table.set("__path", path)?;
table.set_metatable(Some(mt_clone.clone()));
Ok(mlua::Value::Table(table))
Ok(Value::Table(table))
}
_ => Err(mlua::Error::RuntimeError(format!(
"toml-edit: cannot parse {}: {} yet",
value.type_name(),
value
))),
},
toml_edit::Item::None => Ok(mlua::Value::Nil),
toml_edit::Item::None => Ok(Value::Nil),
item => Err(mlua::Error::RuntimeError(format!(
"toml-edit: cannot parse: '{}'",
item
Expand All @@ -82,7 +82,7 @@ where
metatable.set(
"__newindex",
lua.create_function(
move |_, (tbl, key, value): (mlua::Table, mlua::String, mlua::Value)| {
move |_, (tbl, key, value): (mlua::Table, mlua::String, Value)| {
let mut path = tbl.get::<_, Vec<String>>("__path")?;
path.push(key.to_str()?.to_string());

Expand All @@ -108,16 +108,16 @@ where
});

*entry = match value {
mlua::Value::Nil => toml_edit::Item::None,
mlua::Value::String(str) => toml_edit::value(str.to_str()?.to_string()),
mlua::Value::Number(number) => toml_edit::value(
lua.from_value::<mlua::Number>(mlua::Value::Number(number))?,
),
mlua::Value::Integer(int) => toml_edit::value(
lua.from_value::<mlua::Integer>(mlua::Value::Integer(int))?,
),
mlua::Value::Boolean(bool) => toml_edit::value(bool),
mlua::Value::Table(_table) => {
Value::Nil => toml_edit::Item::None,
Value::String(str) => toml_edit::value(str.to_str()?.to_string()),
Value::Number(number) => {
toml_edit::value(lua.from_value::<mlua::Number>(Value::Number(number))?)
}
Value::Integer(int) => {
toml_edit::value(lua.from_value::<mlua::Integer>(Value::Integer(int))?)
}
Value::Boolean(bool) => toml_edit::value(bool),
Value::Table(_table) => {
// Update state data within Lua
// for pair in tbl.pairs() {
// let (key, value): (mlua::Value, mlua::Value) = pair?;
Expand Down Expand Up @@ -148,7 +148,7 @@ where
lua.create_function(move |lua, ()| lua.to_value(&document.borrow().to_string()))?,
)?;

table.set_metatable(Some(metatable));
table.set_metatable(Some(metatable.clone()));

Ok(table)
}
Expand Down Expand Up @@ -178,5 +178,105 @@ pub fn toml_edit(lua: &'static Lua) -> Result<mlua::Table> {
lua.to_value(&tbl)
})?,
)?;
table.set(
"parse_spanned",
lua.create_function(move |lua: &Lua, str: mlua::String| {
let spanned = lua.create_table()?;

let document: ImDocument<String> = match str.to_string_lossy().parse() {
Ok(document) => document,
Err(err) => return Err(err.into_lua_err()),
};

spanned.set(
"span_of",
lua.create_function(
move |lua: &Lua, (path, selector): (mlua::String, Value)| {
let initial_key = Key::new("");

let (key, item) = path.to_str().unwrap().split('.').try_fold(
(&initial_key, document.as_item()),
|acc: (&Key, &toml_edit::Item), next_path| {
acc.1.as_table().unwrap().get_key_value(next_path).ok_or(
mlua::Error::BadArgument {
to: Some("span_of".into()),
pos: 1,
name: Some("path".into()),
cause: format!(
"key '{}' does not exist in the TOML. The full path that was provided: {}",
next_path,
path.to_str().unwrap()
)
.into_lua_err()
.into(),
},
)
},
)?;

match selector {
Value::String(str) if str == "key" => Ok(key
.span()
.map(|val| lua.to_value(&val).unwrap())
.unwrap_or(Value::Nil)),
Value::String(str) if str == "value" => Ok(item
.span()
.map(|val| lua.to_value(&val).unwrap())
.unwrap_or(Value::Nil)),
Value::Integer(num) => Ok(
item
.as_array()
.ok_or(
mlua::Error::BadArgument {
to: Some("span_of".into()),
pos: 2,
name: Some("selector".into()),
cause: format!(
"value {} is not an array (required for numerical selectors)",
path.to_str().unwrap()
)
.into_lua_err()
.into(),
}
)?
.get(num as usize)
.ok_or(
mlua::Error::BadArgument {
to: Some("span_of".into()),
pos: 2,
name: Some("selector".into()),
cause: format!(
"array '{}' does not have a value at index {}. The full path that was provided: {}",
key,
num,
path.to_str().unwrap()
)
.into_lua_err()
.into(),
}
)?
.span()
.map(|val| lua.to_value(&val).unwrap())
.unwrap_or(Value::Nil)),
_ => {
Err(
mlua::Error::BadArgument {
to: Some("span_of".into()),
pos: 2,
name: Some("selector".into()),
cause: r#"expected one of: "key", "value" or a number"#
.into_lua_err()
.into(),
},
)
}
}
},
)?,
)?;

Ok(spanned)
})?,
)?;
Ok(table)
}

0 comments on commit 632a479

Please sign in to comment.