Transparent type conversion in set_prop method
This commit is contained in:
parent
7e247356c7
commit
8678823494
1 changed files with 56 additions and 16 deletions
72
src/lib.rs
72
src/lib.rs
|
@ -10,6 +10,7 @@ use dukbind::{
|
||||||
DUK_ERR_TYPE_ERROR, DUK_ERR_URI_ERROR, DUK_TYPE_BOOLEAN, DUK_TYPE_NONE, DUK_TYPE_NULL,
|
DUK_ERR_TYPE_ERROR, DUK_ERR_URI_ERROR, DUK_TYPE_BOOLEAN, DUK_TYPE_NONE, DUK_TYPE_NULL,
|
||||||
DUK_TYPE_NUMBER, DUK_TYPE_OBJECT, DUK_TYPE_STRING, DUK_TYPE_UNDEFINED,
|
DUK_TYPE_NUMBER, DUK_TYPE_OBJECT, DUK_TYPE_STRING, DUK_TYPE_UNDEFINED,
|
||||||
};
|
};
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -17,7 +18,6 @@ use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
/// An error code representing why an error occurred.
|
/// An error code representing why an error occurred.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
@ -179,13 +179,23 @@ impl<'a> DukObject<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a property on this object.
|
/// Set a property on this object.
|
||||||
pub fn set_prop(&self, name: &str, value: DukValue) -> DukResult<()> {
|
pub fn set_prop<'z, T>(&self, name: &str, value: T) -> DukResult<()>
|
||||||
|
where
|
||||||
|
T: TryInto<DukValue<'z>>,
|
||||||
|
{
|
||||||
let ctx = self.context.ctx.as_ptr();
|
let ctx = self.context.ctx.as_ptr();
|
||||||
unsafe {
|
unsafe {
|
||||||
duk_push_heapptr(ctx, self.heap.as_ptr());
|
duk_push_heapptr(ctx, self.heap.as_ptr());
|
||||||
if duk_is_undefined(ctx, -1) == 0 {
|
if duk_is_undefined(ctx, -1) == 0 {
|
||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
match value {
|
let duk_val = match value.try_into() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
let err_msg = format!("Could not convert parameter to DukValue");
|
||||||
|
return Err(DukError::from_str(err_msg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match duk_val {
|
||||||
DukValue::Undefined => duk_push_undefined(ctx),
|
DukValue::Undefined => duk_push_undefined(ctx),
|
||||||
DukValue::Null => duk_push_null(ctx),
|
DukValue::Null => duk_push_null(ctx),
|
||||||
DukValue::Number(ref n) => {
|
DukValue::Number(ref n) => {
|
||||||
|
@ -267,6 +277,12 @@ impl<'a> From<String> for DukValue<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for DukValue<'a> {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
DukValue::String(String::from(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> TryInto<bool> for DukValue<'a> {
|
impl<'a> TryInto<bool> for DukValue<'a> {
|
||||||
type Error = DukError;
|
type Error = DukError;
|
||||||
|
|
||||||
|
@ -372,28 +388,26 @@ impl DukError {
|
||||||
/// Create a DukError from an error code (no message).
|
/// Create a DukError from an error code (no message).
|
||||||
pub fn from_code(code: DukErrorCode) -> DukError {
|
pub fn from_code(code: DukErrorCode) -> DukError {
|
||||||
DukError {
|
DukError {
|
||||||
code: code,
|
code,
|
||||||
message: None,
|
message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a DukError from an error message (no code).
|
/// Create a DukError from an error message (no code).
|
||||||
pub fn from_str(message: &str) -> DukError {
|
pub fn from_str<T: AsRef<str>>(message: T) -> DukError {
|
||||||
DukError {
|
DukError {
|
||||||
code: DukErrorCode::Error,
|
code: DukErrorCode::Error,
|
||||||
message: Some(message.to_string()),
|
message: Some(String::from(message.as_ref())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a DukError from a code and message.
|
/// Create a DukError from a code and message.
|
||||||
pub fn from(code: DukErrorCode, message: &str) -> DukError {
|
pub fn from(code: DukErrorCode, message: &str) -> DukError {
|
||||||
DukError {
|
DukError {
|
||||||
code: code,
|
code,
|
||||||
message: Some(message.to_string()),
|
message: Some(message.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return the message stored in the DukError (or None if there isn't one).
|
|
||||||
pub fn to_string(&self) -> Option<String> {
|
|
||||||
self.message.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for DukError {}
|
impl Error for DukError {}
|
||||||
|
@ -543,7 +557,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_eval_to_string() {
|
fn test_eval_to_string() {
|
||||||
let ctx = DukContext::new().unwrap();
|
let ctx = DukContext::new().unwrap();
|
||||||
let val: String = ctx.eval_string("'something'.toUpperCase()").unwrap().try_into().unwrap();
|
let val: String = ctx
|
||||||
|
.eval_string("'something'.toUpperCase()")
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
assert_eq!(val.as_str(), "SOMETHING");
|
assert_eq!(val.as_str(), "SOMETHING");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,13 +573,33 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_obj_prop() {
|
fn test_set_obj_prop_str() {
|
||||||
let ctx = DukContext::new().unwrap();
|
let ctx = DukContext::new().unwrap();
|
||||||
let val = ctx.eval_string("({\"some\":\"thing\"})").unwrap();
|
let val = ctx.eval_string("({\"some\":\"thing\"})").unwrap();
|
||||||
let obj = val.as_object().unwrap();
|
let obj = val.as_object().unwrap();
|
||||||
let s = String::from("name");
|
|
||||||
obj.set_prop("other", s.into()).unwrap();
|
obj.set_prop("other", String::from("name")).unwrap();
|
||||||
assert_eq!(obj.encode().unwrap().as_str(), "{\"some\":\"thing\",\"other\":\"name\"}");
|
obj.set_prop("another", "name").unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
obj.encode().unwrap().as_str(),
|
||||||
|
"{\"some\":\"thing\",\"other\":\"name\",\"another\":\"name\"}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_obj_prop_bool() {
|
||||||
|
let ctx = DukContext::new().unwrap();
|
||||||
|
let val = ctx.eval_string("({\"some\":\"thing\"})").unwrap();
|
||||||
|
let obj = val.as_object().unwrap();
|
||||||
|
|
||||||
|
obj.set_prop("other", true).unwrap();
|
||||||
|
obj.set_prop("another", false).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
obj.encode().unwrap().as_str(),
|
||||||
|
"{\"some\":\"thing\",\"other\":true,\"another\":false}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -569,7 +607,9 @@ mod tests {
|
||||||
let ctx = DukContext::new().unwrap();
|
let ctx = DukContext::new().unwrap();
|
||||||
let val = ctx.eval_string("({\"some\":\"thing\"})").unwrap();
|
let val = ctx.eval_string("({\"some\":\"thing\"})").unwrap();
|
||||||
let obj = val.as_object().unwrap();
|
let obj = val.as_object().unwrap();
|
||||||
|
|
||||||
let value: String = obj.get_prop("some").unwrap().try_into().unwrap();
|
let value: String = obj.get_prop("some").unwrap().try_into().unwrap();
|
||||||
|
|
||||||
assert_eq!(value.as_str(), "thing");
|
assert_eq!(value.as_str(), "thing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue