diff --git a/src/conversion.rs b/src/conversion.rs index a06abdcd..da3a7d9a 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -1,12 +1,13 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; -use std::ffi::{CStr, CString}; +use std::ffi::{CStr, CString, OsStr, OsString}; use std::hash::{BuildHasher, Hash}; use std::os::raw::c_int; +use std::path::{Path, PathBuf}; use std::string::String as StdString; use std::{slice, str}; -use bstr::{BStr, BString}; +use bstr::{BStr, BString, ByteVec}; use num_traits::cast; use crate::error::{Error, Result}; @@ -603,6 +604,63 @@ impl IntoLua for &BStr { } } +impl IntoLua for OsString { + #[inline] + fn into_lua(self, lua: &Lua) -> Result { + BString::from( + Vec::from_os_string(self).map_err(|val| Error::ToLuaConversionError { + from: "OsString".into(), + to: "string", + message: Some(format!("Invalid encoding: {:?}", val)), + })?, + ) + .into_lua(lua) + } +} + +impl FromLua for OsString { + #[inline] + fn from_lua(value: Value, lua: &Lua) -> Result { + let ty = value.type_name(); + let bs = BString::from_lua(value, lua)?; + Vec::from(bs) + .into_os_string() + .map_err(|err| Error::FromLuaConversionError { + from: ty, + to: "OsString".into(), + message: Some(format!("{}", err)), + }) + } +} + +impl IntoLua for &OsStr { + #[inline] + fn into_lua(self, lua: &Lua) -> Result { + OsString::from(self).into_lua(lua) + } +} + +impl IntoLua for PathBuf { + #[inline] + fn into_lua(self, lua: &Lua) -> Result { + self.into_os_string().into_lua(lua) + } +} + +impl FromLua for PathBuf { + #[inline] + fn from_lua(value: Value, lua: &Lua) -> Result { + OsString::from_lua(value, lua).map(PathBuf::from) + } +} + +impl IntoLua for &Path { + #[inline] + fn into_lua(self, lua: &Lua) -> Result { + PathBuf::from(self).into_lua(lua) + } +} + #[inline] unsafe fn push_bytes_into_stack(this: T, lua: &RawLua) -> Result<()> where diff --git a/tests/conversion.rs b/tests/conversion.rs index d0e7a079..e61dd32a 100644 --- a/tests/conversion.rs +++ b/tests/conversion.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; -use std::ffi::{CStr, CString}; +use std::ffi::{CStr, CString, OsStr, OsString}; +use std::path::{Path, PathBuf}; use bstr::BString; use maplit::{btreemap, btreeset, hashmap, hashset}; @@ -397,6 +398,55 @@ fn test_bstring_from_lua_buffer() -> Result<()> { Ok(()) } +#[test] +fn test_osstring_into_from_lua() -> Result<()> { + let lua = Lua::new(); + + let s = OsString::from("hello, world"); + + let v = lua.pack(s.as_os_str())?; + assert!(v.is_string()); + assert_eq!(v.as_str().unwrap(), "hello, world"); + + let v = lua.pack(s)?; + assert!(v.is_string()); + assert_eq!(v.as_str().unwrap(), "hello, world"); + + let s = lua.create_string("hello, world")?; + let bstr = lua.unpack::(Value::String(s))?; + assert_eq!(bstr, "hello, world"); + + let bstr = lua.unpack::(Value::Integer(123))?; + assert_eq!(bstr, "123"); + + let bstr = lua.unpack::(Value::Number(-123.55))?; + assert_eq!(bstr, "-123.55"); + + Ok(()) +} + +#[test] +fn test_pathbuf_into_from_lua() -> Result<()> { + let lua = Lua::new(); + + let pb = PathBuf::from(env!("CARGO_TARGET_TMPDIR")); + let pb_str = pb.to_str().unwrap(); + + let v = lua.pack(pb.as_path())?; + assert!(v.is_string()); + assert_eq!(v.as_str().unwrap(), pb_str); + + let v = lua.pack(pb.clone())?; + assert!(v.is_string()); + assert_eq!(v.as_str().unwrap(), pb_str); + + let s = lua.create_string(pb_str)?; + let bstr = lua.unpack::(Value::String(s))?; + assert_eq!(bstr, pb); + + Ok(()) +} + #[test] fn test_option_into_from_lua() -> Result<()> { let lua = Lua::new();