Skip to content

Commit

Permalink
Merge branch 'scl-binding' of git://github.com/juchiast/torchbear, ca…
Browse files Browse the repository at this point in the history
…rgo update
  • Loading branch information
Arnaz87 committed Dec 3, 2018
2 parents b648349 + 9ccb22b commit 5837af0
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 16 deletions.
38 changes: 23 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ git2 = "0.7"
regex = "1"
tantivy = "0.7"
mime_guess = "1.8.6"
scl = "0.0.1"

[dev-dependencies]
tempfile = "3"
Expand Down
2 changes: 1 addition & 1 deletion src/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub mod select;
pub mod git;
pub mod regex;
pub mod mime;

pub mod scl;
// Panics if not included (?)
//#[cfg(feature = "log_bindings")]
pub mod log;
Expand Down
261 changes: 261 additions & 0 deletions src/bindings/scl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
use rlua::FromLua;
use rlua::ToLua;

fn to_rlua_value(lua: &rlua::Lua, val: scl::Value) -> rlua::Value {
match val {
scl::Value::Boolean(b) => b.to_lua(lua).unwrap(),
scl::Value::Integer(i) => i.to_lua(lua).unwrap(),
scl::Value::Float(f) => f.to_lua(lua).unwrap(),
scl::Value::String(s) => s.to_lua(lua).unwrap(),
scl::Value::Dict(d) => d
.into_iter()
.map(|(k, v)| (k, to_rlua_value(lua, v)))
.collect::<std::collections::BTreeMap<_, _>>()
.to_lua(lua)
.unwrap(),
scl::Value::Array(a) => a
.into_iter()
.map(|v| to_rlua_value(lua, v))
.collect::<Vec<_>>()
.to_lua(lua)
.unwrap(),
scl::Value::Date(d) => {
let mut map = std::collections::BTreeMap::new();
map.insert("day", d.day as u16);
map.insert("month", d.month as u16);
map.insert("year", d.year);
map.to_lua(lua).unwrap()
}
}
}

fn to_date(lua: &rlua::Lua, t: &rlua::Table) -> rlua::Result<scl::Date> {
if t.len()? == 3
|| t.contains_key("day")?
|| t.contains_key("month")?
|| t.contains_key("year")?
{
let day = <_>::from_lua(t.get("day")?, lua)?;
let month = <_>::from_lua(t.get("month")?, lua)?;
let year = <_>::from_lua(t.get("year")?, lua)?;
Ok(scl::Date { day, month, year })
} else {
Err(rlua::Error::external(failure::err_msg("not a date")))
}
}

fn to_scl_value(lua: &rlua::Lua, val: rlua::Value) -> scl::Value {
match &val {
rlua::Value::Boolean(_) => scl::Value::Boolean(<_>::from_lua(val, lua).unwrap()),
rlua::Value::Integer(_) => scl::Value::Integer(<_>::from_lua(val, lua).unwrap()),
rlua::Value::Number(_) => scl::Value::Float(<_>::from_lua(val, lua).unwrap()),
rlua::Value::String(_) => scl::Value::String(<_>::from_lua(val, lua).unwrap()),
rlua::Value::Table(_) => {
let t = if let rlua::Value::Table(t) = val {
t
} else {
unreachable!();
};
if t.contains_key(1).unwrap() {
let len = t.len().unwrap() as usize;
let mut vec = Vec::new();
for i in 1..=len {
vec.push(to_scl_value(lua, t.get(i).unwrap()))
}
scl::Value::Array(vec)
} else if let Ok(date) = to_date(lua, &t) {
scl::Value::Date(date)
} else {
let mut dict = std::collections::BTreeMap::new();
for pair in t.pairs::<String, rlua::Value>() {
let (k, v) = pair.unwrap();
dict.insert(k, to_scl_value(lua, v));
}
scl::Value::Dict(dict)
}
}
_ => panic!("Not supported"),
}
}

fn escape(s: String) -> String {
if s.contains(r##"""""##) {
// escape \n and "
// return "\"".to_owned() + &s.replace('"', r##"\""##).replace('\n', "\\n") + "\"";
//
// this doesn't work, see:
// https://github.com/Keats/scl/issues/10
//
// Because it doesn't work, just panic instead
panic!("Don't use a string containing \"\"\"");
} else {
// use multiline string
r##"""""##.to_owned() + &s + r##"""""##
}
}

fn scl_decode(d: scl::Dict) -> String {
let mut s = String::new();
for (k, v) in d {
s += &k;
s += "=";
s += &to_string(v);
s += "\n";
}
s
}

fn to_string(val: scl::Value) -> String {
match val {
scl::Value::Boolean(b) => if b { "true" } else { "false" }.to_owned(),
scl::Value::Integer(i) => i.to_string(),
scl::Value::Float(f) => f.to_string(),
scl::Value::String(s) => escape(s),
scl::Value::Date(d) => format!("{:04}-{:02}-{:02}", d.year, d.month, d.day),
scl::Value::Array(a) => {
let mut s = "[".to_owned();
for v in a {
s += &to_string(v);
s += ",";
}
s += "]";
s
}
scl::Value::Dict(d) => {
let mut s = "{".to_owned();
for (k, v) in d {
s += &k;
s += "=";
s += &to_string(v);
s += ",";
}
s += "}";
s
}
}
}

pub fn init(lua: &rlua::Lua) -> Result<(), rlua::Error> {
// Decode string to a table
let module = lua.create_table()?;
module.set(
"to_table",
lua.create_function(|lua, text: String| {
let dict: scl::Dict = scl::parse_str(&text).unwrap();
Ok(to_rlua_value(lua, scl::Value::Dict(dict)))
})?,
)?;

// Encode table to a string
module.set(
"from_table",
lua.create_function(|lua, table: rlua::Table| {
let val = to_scl_value(lua, rlua::Value::Table(table));
if let scl::Value::Dict(d) = val {
Ok(scl_decode(d))
} else {
unreachable!();
}
})?,
)?;

lua.globals().set("scl", module)?;

Ok(())
}

#[cfg(test)]
mod tests {
#[test]
fn test_decode() {
static TEXT: &str = r##"
owner = {
name = "Vincent Prouillet",
dob = 1979-05-27, # first-class date type
}
database = {
ports = [ 8001, 8001, 8002 ],
connection_max = 5000,
enabled = true,
}
servers = {
max_upload_size = 10MB, # first class byte size
alpha = {
ip = "10.0.0.1",
dc = "eqdc10",
},
}
clients = {
data = [
["gamma"],
[1],
],
}
"##;
let lua = rlua::Lua::new();
super::init(&lua).unwrap();
lua.globals().set("TEXT", TEXT).unwrap();
lua.exec::<_, rlua::Value>(
r##"
local x = scl.to_table(TEXT)
assert(x.owner.name == "Vincent Prouillet")
assert(x.owner.dob.year == 1979)
assert(x.owner.dob.month == 5)
assert(x.owner.dob.day == 27)
assert(#x.database.ports == 3)
assert(x.database.ports[1] == 8001)
assert(x.database.ports[2] == 8001)
assert(x.database.ports[3] == 8002)
assert(x.database.connection_max == 5000)
assert(x.database.enabled == true)
assert(x.servers.max_upload_size == 10000000)
assert(x.servers.alpha.ip == "10.0.0.1")
assert(x.servers.alpha.dc == "eqdc10")
assert(x.clients.data[1][1] == "gamma")
assert(x.clients.data[2][1] == 1)
"##,
None,
)
.unwrap();
}

#[test]
fn test_encode() {
let lua = rlua::Lua::new();
super::init(&lua).unwrap();
lua.exec::<_, rlua::Value>(
r##"
local x = {
x=0,
y=true,
z="a\nb",
a=1.2,
b={c=1},
d={day=1,month=2,year=2018},
e={2, 3, 4},
}
local s = scl.from_table(x)
print(s)
local y = scl.to_table(s)
-- don't mess with floating point number
-- assert(y.a == 1.2)
assert(y.b.c == 1)
assert(y.d.year == 2018)
assert(y.d.month == 2)
assert(y.d.day == 1)
assert(y.e[1] == 2)
assert(y.e[2] == 3)
assert(y.e[3] == 4)
assert(#y.e == 3)
assert(y.x == 0)
assert(y.y == true)
assert(y.z == "a\nb")
"##,
None,
)
.unwrap();
}
}
Loading

0 comments on commit 5837af0

Please sign in to comment.