use ::{_API};
use capi::sctypes::*;
use capi::scvalue::{VALUE_UNIT_TYPE_STRING, VALUE_UNIT_TYPE_OBJECT, VALUE_UNIT_UNDEFINED};
pub use capi::scvalue::{VALUE_RESULT, VALUE_STRING_CVT_TYPE, VALUE_TYPE};
use capi::scvalue::VALUE;
use ::om::IAsset;
pub struct Value
{
data: VALUE,
tmp: * mut Value,
}
unsafe impl Send for Value {}
impl Value {
pub const fn new() -> Value {
Value { data: VALUE::new(), tmp: ::std::ptr::null_mut() }
}
pub fn array(length: usize) -> Value {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), length as i32, VALUE_TYPE::T_ARRAY as UINT, 0);
return me;
}
pub fn map() -> Value {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), 0i32, VALUE_TYPE::T_MAP as UINT, 0);
return me;
}
pub const fn null() -> Value {
let mut me = Value::new();
me.data.t = VALUE_TYPE::T_NULL;
return me;
}
pub const fn nothing() -> Value {
let mut me = Value::new();
me.data.t = VALUE_TYPE::T_UNDEFINED;
me.data.u = VALUE_UNIT_UNDEFINED::UT_NOTHING as UINT;
return me;
}
pub fn symbol(val: &str) -> Value {
let mut me = Value::new();
me.assign_str(val, VALUE_UNIT_TYPE_STRING::SYMBOL);
return me;
}
pub fn error(val: &str) -> Value {
let mut me = Value::new();
me.assign_str(val, VALUE_UNIT_TYPE_STRING::ERROR);
return me;
}
pub fn color(val: u32) -> Value {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), val as i32, VALUE_TYPE::T_COLOR as u32, 0);
return me;
}
pub fn duration(val: f64) -> Value {
let mut me = Value::new();
(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_DURATION as u32, 0);
return me;
}
pub fn angle(val: f64) -> Value {
let mut me = Value::new();
(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_ANGLE as u32, 0);
return me;
}
pub fn parse(val: &str) -> Result<Value, usize> {
return Value::parse_as(val, VALUE_STRING_CVT_TYPE::JSON_LITERAL);
}
pub fn parse_as(val: &str, how: VALUE_STRING_CVT_TYPE) -> Result<Value, usize> {
let mut me = Value::new();
let (s,n) = s2wn!(val);
let ok: u32 = (_API.ValueFromString)(me.as_ptr(), s.as_ptr(), n, how);
if ok == 0 {
Ok(me)
} else {
Err(ok as usize)
}
}
pub fn to_asset<T>(&self) -> Option<&mut IAsset<T>> {
if self.is_asset() {
let mut val = 0_i64;
if (_API.ValueInt64Data)(self.as_cptr(), &mut val) == VALUE_RESULT::OK {
let ptr = val as usize as *mut IAsset<T>;
let asset = unsafe { &mut *ptr };
return Some(asset);
}
}
return None;
}
pub fn as_mut_ptr(&mut self) -> *mut VALUE {
&mut self.data as *mut VALUE
}
#[doc(hidden)]
pub fn as_ptr(&mut self) -> *mut VALUE {
&mut self.data as *mut VALUE
}
#[doc(hidden)]
pub fn as_cptr(&self) -> *const VALUE {
&self.data as *const VALUE
}
pub const fn get_type(&self) -> VALUE_TYPE {
return self.data.t;
}
pub const fn full_type(&self) -> (VALUE_TYPE, UINT) {
return (self.data.t, self.data.u);
}
pub fn isolate(&mut self) {
(_API.ValueIsolate)(self.as_ptr());
}
pub fn clear(&mut self) -> &mut Value {
(_API.ValueClear)(self.as_ptr());
self
}
pub fn len(&self) -> usize {
let mut n: INT = 0;
(_API.ValueElementsCount)(self.as_cptr(), &mut n);
return n as usize;
}
pub fn push<T: Into<Value>>(&mut self, src: T) {
(_API.ValueNthElementValueSet)(self.as_ptr(), self.len() as INT, src.into().as_cptr());
}
pub fn set<T: Into<Value>>(&mut self, index: usize, src: T) {
(_API.ValueNthElementValueSet)(self.as_ptr(), index as INT, src.into().as_cptr());
}
pub fn get(&self, index: usize) -> Value {
let mut v = Value::new();
(_API.ValueNthElementValue)(self.as_cptr(), index as INT, v.as_ptr());
return v;
}
pub fn set_item<TKey: Into<Value>, TValue: Into<Value>>(&mut self, key: TKey, value: TValue) {
(_API.ValueSetValueToKey)(self.as_ptr(), key.into().as_cptr(), value.into().as_cptr());
}
pub fn get_item<T: Into<Value>>(&self, key: T) -> Value {
let mut v = Value::new();
(_API.ValueGetValueOfKey)(self.as_cptr(), key.into().as_cptr(), v.as_ptr());
return v;
}
pub fn key_at(&self, index: usize) -> Value {
let mut v = Value::new();
(_API.ValueNthElementKey)(self.as_cptr(), index as INT, v.as_ptr());
return v;
}
pub fn keys(&self) -> KeyIterator {
KeyIterator {
base: self,
index: 0,
count: self.len(),
}
}
pub fn values(&self) -> SeqIterator {
SeqIterator {
base: self,
index: 0,
count: self.len(),
}
}
pub fn items(&self) -> Vec<(Value, Value)> {
type VecType = Vec<(Value, Value)>;
let mut result = Vec::with_capacity(self.len());
extern "system" fn on_pair(param: LPVOID, pkey: *const VALUE, pval: *const VALUE) -> BOOL {
assert!(!param.is_null());
unsafe {
let result = param as *mut VecType;
let result = &mut *result;
let item = (Value::copy_from(pkey), Value::copy_from(pval));
result.push(item);
}
return true as BOOL;
}
let ptr = &mut result as *mut VecType;
(_API.ValueEnumElements)(self.as_cptr(), on_pair, ptr as LPVOID);
return result;
}
pub fn to_int(&self) -> Option<i32> {
let mut val = 0i32;
match (_API.ValueIntData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val),
_ => None
}
}
pub fn to_bool(&self) -> Option<bool> {
let mut val = 0i32;
match (_API.ValueIntData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val != 0),
_ => None
}
}
pub fn to_float(&self) -> Option<f64> {
let mut val = 0f64;
match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val),
_ => None
}
}
pub fn to_color(&self) -> Option<u32> {
let mut val = 0i32;
match (_API.ValueIntData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val as u32),
_ => None
}
}
pub fn to_duration(&self) -> Option<f64> {
let mut val = 0f64;
match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val),
_ => None
}
}
pub fn to_angle(&self) -> Option<f64> {
let mut val = 0f64;
match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
VALUE_RESULT::OK => Some(val),
_ => None
}
}
pub fn as_string(&self) -> Option<String> {
let mut s = 0 as LPCWSTR;
let mut n = 0_u32;
match (_API.ValueStringData)(self.as_cptr(), &mut s, &mut n) {
VALUE_RESULT::OK => Some(::utf::w2sn(s, n as usize)),
_ => None
}
}
pub fn into_string(mut self) -> String {
(_API.ValueToString)(self.as_ptr(), VALUE_STRING_CVT_TYPE::JSON_LITERAL);
return self.as_string().unwrap();
}
pub fn as_bytes(&self) -> Option<&[u8]> {
let mut s = 0 as LPCBYTE;
let mut n = 0_u32;
match (_API.ValueBinaryData)(self.as_cptr(), &mut s, &mut n) {
VALUE_RESULT::OK => Some(unsafe { ::std::slice::from_raw_parts(s, n as usize) }),
_ => None
}
}
pub fn to_bytes(&self) -> Option<Vec<u8>> {
self.as_bytes().map(ToOwned::to_owned)
}
pub fn call(&self, this: Option<Value>, args: &[Value], name: Option<&str>) -> Result<Value, VALUE_RESULT> {
let mut rv = Value::new();
let argv = Value::pack_args(args);
let name = s2w!(name.unwrap_or(""));
let ok = (_API.ValueInvoke)(self.as_cptr(), this.unwrap_or_default().as_ptr(),
argv.len() as UINT, argv.as_ptr(), rv.as_ptr(), name.as_ptr());
match ok {
VALUE_RESULT::OK => Ok(rv),
_ => Err(ok)
}
}
#[doc(hidden)]
pub fn pack_to(&self, dst: &mut VALUE) {
(_API.ValueCopy)(dst, self.as_cptr());
}
#[doc(hidden)]
pub fn pack_args(args: &[Value]) -> Vec<VALUE> {
let argc = args.len();
let mut argv: Vec<VALUE> = Vec::with_capacity(argc);
argv.resize(argc, VALUE::default());
for i in 0..argc {
args[i].pack_to(&mut argv[i]);
}
return argv;
}
#[doc(hidden)]
pub unsafe fn unpack_from(args: * const VALUE, count: UINT) -> Vec<Value> {
let argc = count as usize;
let mut argv: Vec<Value> = Vec::with_capacity(argc);
assert!(argc == 0 || !args.is_null());
let args = ::std::slice::from_raw_parts(args, argc);
for arg in args {
argv.push(Value::copy_from(arg));
}
return argv;
}
#[doc(hidden)]
unsafe fn copy_from(ptr: *const VALUE) -> Value {
assert!(!ptr.is_null());
let mut v = Value::new();
(_API.ValueCopy)(v.as_ptr(), ptr);
return v;
}
#[allow(clippy::mut_from_ref)]
fn ensure_tmp_mut(&self) -> &mut Value {
let cp = self as *const Value;
let mp = cp as *mut Value;
let me = unsafe { &mut *mp };
return me.ensure_tmp();
}
fn ensure_tmp(&mut self) -> &mut Value {
if self.tmp.is_null() {
let tmp = Box::new(Value::new());
self.tmp = Box::into_raw(tmp);
}
return unsafe { &mut *self.tmp };
}
pub fn is_empty(&self) -> bool {
self.is_undefined() || self.len() == 0
}
#[allow(missing_docs)]
pub const fn is_undefined(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_UNDEFINED as u32 && self.data.u == 0
}
#[allow(missing_docs)]
pub const fn is_null(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_NULL as u32
}
#[allow(missing_docs)]
pub const fn is_nothing(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_UNDEFINED as u32 && self.data.u == VALUE_UNIT_UNDEFINED::UT_NOTHING as UINT
}
#[allow(missing_docs)]
pub const fn is_bool(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_BOOL as u32
}
#[allow(missing_docs)]
pub const fn is_int(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_INT as u32
}
#[allow(missing_docs)]
pub const fn is_float(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_FLOAT as u32
}
#[allow(missing_docs)]
pub const fn is_bytes(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_BYTES as u32
}
#[allow(missing_docs)]
pub const fn is_string(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_STRING as u32
}
#[allow(missing_docs)]
pub const fn is_symbol(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_STRING as u32 && self.data.u == VALUE_UNIT_TYPE_STRING::SYMBOL as UINT
}
#[allow(missing_docs)]
pub const fn is_error_string(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_STRING as u32 && self.data.u == VALUE_UNIT_TYPE_STRING::ERROR as UINT
}
#[allow(missing_docs)]
pub const fn is_date(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_DATE as u32
}
#[allow(missing_docs)]
pub const fn is_currency(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_CURRENCY as u32
}
#[allow(missing_docs)]
pub const fn is_color(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_COLOR as u32
}
#[allow(missing_docs)]
pub const fn is_duration(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_DURATION as u32
}
#[allow(missing_docs)]
pub const fn is_angle(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_ANGLE as u32
}
#[allow(missing_docs)]
pub const fn is_map(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_MAP as u32
}
#[allow(missing_docs)]
pub const fn is_array(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_ARRAY as u32
}
#[allow(missing_docs)]
pub const fn is_function(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_FUNCTION as u32
}
#[allow(missing_docs)]
pub fn is_native_function(&self) -> bool {
(_API.ValueIsNativeFunctor)(self.as_cptr()) != 0
}
#[allow(missing_docs)]
pub const fn is_object(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32
}
#[allow(missing_docs)]
pub const fn is_asset(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_ASSET as u32
}
pub const fn is_primitive(&self) -> bool {
use capi::scvalue::VALUE_TYPE::*;
matches!(self.data.t,
T_UNDEFINED
| T_NULL
| T_BOOL
| T_INT
| T_FLOAT
| T_DATE
)
}
#[allow(missing_docs)]
pub const fn is_object_array(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::ARRAY as UINT
}
#[allow(missing_docs)]
pub const fn is_object_map(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::OBJECT as UINT
}
#[allow(missing_docs)]
pub const fn is_object_class(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::OBJECT as UINT
}
#[allow(missing_docs)]
pub const fn is_object_native(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::NATIVE as UINT
}
#[allow(missing_docs)]
pub const fn is_object_function(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::FUNCTION as UINT
}
#[allow(missing_docs)]
pub const fn is_object_error(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::ERROR as UINT
}
#[allow(missing_docs)]
pub const fn is_dom_element(&self) -> bool {
self.data.t as u32 == VALUE_TYPE::T_DOM_OBJECT as u32
}
#[allow(missing_docs)]
pub const fn is_varray(&self) -> bool {
self.is_array() || self.is_object()
}
#[allow(missing_docs)]
pub const fn is_vmap(&self) -> bool {
self.is_map() || self.is_object_map()
}
#[allow(missing_docs)]
pub fn is_vfunction(&self) -> bool {
self.is_function() || self.is_object_function() || self.is_native_function()
}
#[allow(missing_docs)]
pub const fn is_verror(&self) -> bool {
self.is_error_string() || self.is_object_error()
}
fn assign_str(&mut self, val: &str, unit: VALUE_UNIT_TYPE_STRING) -> VALUE_RESULT {
let (s,n) = s2wn!(val);
return (_API.ValueStringDataSet)(self.as_ptr(), s.as_ptr(), n, unit as UINT);
}
}
impl ::std::fmt::Display for Value {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let copy = self.clone();
let re = copy.into_string();
f.write_str(&re)
}
}
impl ::std::fmt::Debug for Value {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let mut tname = format!("{:?}", self.data.t);
if self.is_undefined() || self.is_null() {
return f.write_str(&tname[2..].to_lowercase());
} else if self.is_nothing() {
return f.write_str("nothing");
} else if self.is_string() && self.data.u != 0 {
let units = [
("file", 0xfffe), ("symbol", 0xffff),
("string", 0), ("error", 1), ("secure", 2),
("url", 3), ("selector", 4),
];
tname.push(':');
if let Some(name) = units.iter().find(|&&x| x.1 == self.data.u) {
tname.push_str(name.0);
} else {
tname.push_str(&self.data.u.to_string());
}
} else if self.is_object() {
let units = ["array", "object", "class", "native", "function", "error"];
let u = self.data.u as usize;
tname.push(':');
if u < units.len() {
tname.push_str(units[u]);
} else {
tname.push_str(&u.to_string());
}
} else if self.data.u != 0 {
}
f.write_str(&tname[2..].to_lowercase())?;
f.write_str(":")?;
write!(f, "{}", &self)
}
}
impl Drop for Value {
fn drop(&mut self) {
if !self.tmp.is_null() {
let _drop_tmp = unsafe { Box::from_raw(self.tmp) };
}
if std::thread::panicking() {
if self.is_primitive() {
return;
}
}
(_API.ValueClear)(self.as_ptr());
}
}
impl Default for Value {
fn default() -> Self {
return Value::new();
}
}
impl Clone for Value {
fn clone(&self) -> Self {
let mut dst = Value::new();
(_API.ValueCopy)(dst.as_ptr(), self.as_cptr());
return dst;
}
}
impl ::std::cmp::PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
let eq = (_API.ValueCompare)(self.as_cptr(), other.as_cptr());
matches!(eq, VALUE_RESULT::OK_TRUE)
}
}
impl ::std::ops::Index<usize> for Value {
type Output = Value;
fn index(&self, index: usize) -> &Self::Output {
let tmp = self.ensure_tmp_mut();
(_API.ValueNthElementValue)(self.as_cptr(), index as INT, tmp.as_ptr());
return tmp;
}
}
#[cfg(notworking)]
impl ::std::ops::IndexMut<usize> for Value {
fn index_mut(&mut self, index: usize) -> &mut Value {
let tmp = self.ensure_tmp_mut();
(_API.ValueNthElementValue)(self.as_cptr(), index as INT, tmp.as_ptr());
return tmp;
}
}
impl ::std::ops::Index<Value> for Value {
type Output = Value;
fn index(&self, key: Value) -> &Self::Output {
let tmp = self.ensure_tmp_mut();
(_API.ValueGetValueOfKey)(self.as_cptr(), key.as_cptr(), tmp.as_ptr());
return tmp;
}
}
impl ::std::ops::Index<&'static str> for Value {
type Output = Value;
fn index(&self, key: &'static str) -> &Self::Output {
let tmp = self.ensure_tmp_mut();
(_API.ValueGetValueOfKey)(self.as_cptr(), Value::from(key).as_cptr(), tmp.as_ptr());
return tmp;
}
}
#[cfg(notworking)]
impl ::std::ops::IndexMut<Value> for Value {
fn index_mut<'a>(&'a mut self, key: Value) -> &'a mut Value {
let ptr = self.as_ptr();
let tmp = self.ensure_tmp();
(_API.ValueSetValueToKey)(ptr, key.as_cptr(), tmp.as_ptr());
return tmp;
}
}
impl From<()> for Value {
fn from(_: ()) -> Self {
Value::new()
}
}
impl<'a> From<&'a VALUE> for Value {
fn from(val: &'a VALUE) -> Self {
unsafe { Value::copy_from(val as *const _) }
}
}
impl From<i32> for Value {
fn from(val: i32) -> Self {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), val, VALUE_TYPE::T_INT as UINT, 0);
return me;
}
}
impl From<&i32> for Value {
fn from(val: &i32) -> Self {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), *val, VALUE_TYPE::T_INT as UINT, 0);
return me;
}
}
impl From<f64> for Value {
fn from(val: f64) -> Self {
let mut me = Value::new();
(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_FLOAT as UINT, 0);
return me;
}
}
impl From<&f64> for Value {
fn from(val: &f64) -> Self {
let mut me = Value::new();
(_API.ValueFloatDataSet)(me.as_ptr(), *val, VALUE_TYPE::T_FLOAT as UINT, 0);
return me;
}
}
impl From<bool> for Value {
fn from(val: bool) -> Self {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), val as INT, VALUE_TYPE::T_BOOL as UINT, 0);
return me;
}
}
impl From<&bool> for Value {
fn from(val: &bool) -> Self {
let mut me = Value::new();
(_API.ValueIntDataSet)(me.as_ptr(), *val as INT, VALUE_TYPE::T_BOOL as UINT, 0);
return me;
}
}
impl<'a> From<&'a str> for Value {
fn from(val: &'a str) -> Self {
let mut me = Value::new();
me.assign_str(val, VALUE_UNIT_TYPE_STRING::STRING);
return me;
}
}
impl From<String> for Value {
fn from(val: String) -> Self {
let mut me = Value::new();
me.assign_str(&val, VALUE_UNIT_TYPE_STRING::STRING);
return me;
}
}
impl<'a> From<&'a String> for Value {
fn from(val: &'a String) -> Self {
let mut me = Value::new();
me.assign_str(val, VALUE_UNIT_TYPE_STRING::STRING);
return me;
}
}
impl ::std::str::FromStr for Value {
type Err = VALUE_RESULT;
fn from_str(val: &str) -> Result<Self, Self::Err> {
Value::parse(val).or(Err(VALUE_RESULT::BAD_PARAMETER))
}
}
impl<'a> From<&'a [u8]> for Value {
fn from(val: &'a [u8]) -> Self {
let mut me = Value::new();
(_API.ValueBinaryDataSet)(me.as_ptr(), val.as_ptr(), val.len() as UINT, VALUE_TYPE::T_BYTES as UINT, 0);
return me;
}
}
impl From<std::time::SystemTime> for Value {
fn from(val: std::time::SystemTime) -> Self {
let mut me = Value::new();
if let Ok(epoch) = val.duration_since(std::time::UNIX_EPOCH) {
let ns = epoch.as_nanos() / 100;
(_API.ValueInt64DataSet)(me.as_ptr(), ns as i64, VALUE_TYPE::T_DATE as u32, 0);
}
me
}
}
impl<T, E> From<Result<T, E>> for Value where T: Into<Value>, E: std::fmt::Display {
fn from(val: Result<T, E>) -> Self {
match val {
Ok(v) => v.into(),
Err(e) => Value::error(&e.to_string()),
}
}
}
impl ::std::iter::FromIterator<Value> for Value {
fn from_iter<I: IntoIterator<Item=Value>>(iterator: I) -> Self {
let iterator = iterator.into_iter();
let capacity = iterator.size_hint().0;
let mut v = Value::array(capacity);
for (i, m) in iterator.enumerate() {
v.set(i, m);
}
return v;
}
}
impl ::std::iter::FromIterator<i32> for Value {
fn from_iter<I: IntoIterator<Item=i32>>(iterator: I) -> Self {
let iterator = iterator.into_iter();
let capacity = iterator.size_hint().0;
let mut v = Value::array(capacity);
for (i, m) in iterator.enumerate() {
v.set(i, Value::from(m));
}
return v;
}
}
impl ::std::iter::FromIterator<f64> for Value {
fn from_iter<I: IntoIterator<Item=f64>>(iterator: I) -> Self {
let iterator = iterator.into_iter();
let capacity = iterator.size_hint().0;
let mut v = Value::array(capacity);
for (i, m) in iterator.enumerate() {
v.set(i, Value::from(m));
}
return v;
}
}
impl<'a> ::std::iter::FromIterator<&'a str> for Value {
fn from_iter<I: IntoIterator<Item=&'a str>>(iterator: I) -> Self {
let iterator = iterator.into_iter();
let capacity = iterator.size_hint().0;
let mut v = Value::array(capacity);
for (i, m) in iterator.enumerate() {
v.set(i, Value::from(m));
}
return v;
}
}
impl ::std::iter::FromIterator<String> for Value {
fn from_iter<I: IntoIterator<Item=String>>(iterator: I) -> Self {
let iterator = iterator.into_iter();
let capacity = iterator.size_hint().0;
let mut v = Value::array(capacity);
for (i, m) in iterator.enumerate() {
v.set(i, Value::from(m));
}
return v;
}
}
impl<F, R> From<F> for Value
where
F: Fn(&[Value]) -> R,
R: Into<Value>,
{
fn from(f: F) -> Value {
let mut v = Value::new();
let boxed = Box::new(f);
let ptr = Box::into_raw(boxed); (_API.ValueNativeFunctorSet)(v.as_ptr(), _functor_invoke::<F,R>, _functor_release::<F>, ptr as LPVOID);
return v;
}
}
impl<T> From<Box<IAsset<T>>> for Value {
fn from(ptr: Box<IAsset<T>>) -> Value {
let ptr = Box::into_raw(ptr);
let mut me = Value::new();
(_API.ValueInt64DataSet)(me.as_ptr(), ptr as usize as i64, VALUE_TYPE::T_ASSET as u32, 0);
return me;
}
}
extern "C" fn _functor_release<F>(tag: LPVOID)
{
let ptr = tag as *mut F;
let boxed = unsafe { Box::from_raw(ptr) };
drop(boxed);
}
extern "C" fn _functor_invoke<F, R>(tag: LPVOID, argc: UINT, argv: *const VALUE, retval: *mut VALUE)
where
F: Fn(&[Value]) -> R,
R: Into<Value>,
{
let ptr = tag as *mut F;
let me = unsafe { &mut *ptr };
let retval = unsafe { &mut *retval };
let args = unsafe { Value::unpack_from(argv, argc) };
let rv = me(&args);
let rv: Value = rv.into();
rv.pack_to(retval)
}
pub trait FromValue {
fn from_value(v: &Value) -> Option<Self> where Self: Sized;
}
impl FromValue for Value {
fn from_value(v: &Value) -> Option<Self> {
Some(v.clone())
}
}
impl FromValue for bool {
fn from_value(v: &Value) -> Option<Self> {
v.to_bool()
}
}
impl FromValue for i32 {
fn from_value(v: &Value) -> Option<Self> {
v.to_int()
}
}
impl FromValue for f64 {
fn from_value(v: &Value) -> Option<Self> {
v.to_float()
}
}
impl FromValue for Vec<u8> {
fn from_value(v: &Value) -> Option<Self> {
v.to_bytes()
}
}
impl FromValue for String {
fn from_value(v: &Value) -> Option<Self> {
v.as_string()
}
}
#[doc(hidden)]
pub struct KeyIterator<'a> {
base: &'a Value,
index: usize,
count: usize,
}
impl<'a> ::std::iter::Iterator for KeyIterator<'a> {
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.count {
self.index += 1;
Some(self.base.key_at(self.index - 1))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remain = self.count - self.index;
(remain, Some(remain))
}
fn count(self) -> usize {
self.count
}
}
impl<'a> ::std::iter::DoubleEndedIterator for KeyIterator<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.index == self.count || self.count == 0 {
None
} else {
self.count -= 1;
Some(self.base.key_at(self.count))
}
}
}
#[doc(hidden)]
pub struct SeqIterator<'a> {
base: &'a Value,
index: usize,
count: usize,
}
impl<'a> ::std::iter::Iterator for SeqIterator<'a> {
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.count {
self.index += 1;
Some(self.base.get(self.index - 1))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remain = self.count - self.index;
(remain, Some(remain))
}
fn count(self) -> usize {
self.count
}
}
impl<'a> ::std::iter::DoubleEndedIterator for SeqIterator<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.index == self.count || self.count == 0 {
None
} else {
self.count -= 1;
Some(self.base.get(self.count))
}
}
}
impl<'a> ::std::iter::IntoIterator for &'a Value {
type Item = Value;
type IntoIter = SeqIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
self.values()
}
}
#[cfg(test)]
mod tests {
#![allow(unused_imports)]
use super::{Value, FromValue};
use capi::scvalue::{VALUE, VALUE_TYPE};
use std::mem;
use ::{_API};
fn check1(a: i32) {
assert_eq!(a, 12);
}
#[test]
fn test_from_value() {
let v = Value::from(12);
check1(
match FromValue::from_value(&v) {
Some(x) => { x },
None => { return; }
}
);
}
#[test]
fn test_value_layout() {
assert_eq!(mem::size_of::<VALUE_TYPE>(), 4);
assert_eq!(mem::size_of::<VALUE>(), 16);
}
#[test]
fn test_abi() {
let mut data = VALUE { t: VALUE_TYPE::T_UNDEFINED, u: 0, d: 0 };
assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
(_API.ValueInit)(&mut data);
assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
(_API.ValueClear)(&mut data);
assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
}
}