sciter/
value.rs

1/*! Rust interface to the [`sciter::value`](https://github.com/c-smile/sciter-sdk/blob/master/include/value.h).
2
3Sciter [`Value`](struct.Value.html) holds superset of JSON objects.
4
5It can contain as pure JSON objects (numbers, strings, maps and arrays) as internal objects like DOM elements,
6proxies of script functions, objects and arrays.
7
8
9## Basic usage
10
11You can create an empty (undefined) Sciter value with [`Value::new()`](struct.Value.html):
12
13```
14use sciter::Value;
15
16let v = Value::new();
17assert!(v.is_undefined());
18assert!(!v.is_null());
19```
20
21Or explicitly create `Value` of the specified type:
22
23```
24use sciter::Value;
25
26let v = Value::null();
27assert!(v.is_null());
28
29let v = Value::symbol("hello");
30assert!(v.is_symbol());
31assert!(v.is_string());
32
33let v = Value::error("hello");
34assert!(v.is_error_string());
35assert!(v.is_string());
36
37// allocate a new array with 4 empty elements
38let v = Value::array(4);
39assert!(v.is_array());
40assert!(v.len() == 4);
41
42// allocate a new value with map type
43let v = Value::map();
44assert!(v.is_map());
45assert!(v.len() == 0);
46
47```
48
49Also there is conversion from Rust types:
50
51```
52use sciter::Value;
53
54let v = Value::from(true);
55assert!(v.is_bool());
56
57let v = Value::from(1);
58assert!(v.is_int());
59
60let v = Value::from(1.0);
61assert!(v.is_float());
62
63let v = Value::from("hello");
64assert!(v.is_string());
65
66let v = Value::from(b"123".as_ref());
67assert!(v.is_bytes());
68```
69
70And from a sequence of objects:
71
72```
73use sciter::Value;
74
75let v: Value = ["1","2","3"].iter().cloned().collect();
76assert!(v.is_array());
77assert_eq!(v.len(), 3);
78
79assert_eq!(v[0], Value::from("1"));
80```
81
82And also there is a couple of macros for container literals with specific type
83which are just shorthands for manual construction using the
84[`set_item()`](struct.Value.html#method.set_item) and [`push()`](struct.Value.html#method.push)
85methods:
86
87```
88# #[macro_use] extern crate sciter;
89# fn main() {
90let map = vmap! {
91  "one" => 1,
92  "two" => 2.0,
93  "three" => "",
94};
95assert!(map.is_map());
96assert_eq!(map.len(), 3);
97
98let array = varray![1, 2.0, "three"];
99assert!(array.is_array());
100assert_eq!(array.len(), 3);
101# }
102```
103
104To access its contents you should use one of [`to_`](struct.Value.html#method.to_int) methods:
105
106```
107use sciter::Value;
108
109let v = Value::from(4);
110assert_eq!(v.to_int(), Some(4));
111```
112
113Note that there are two functions that convert `Value` to JSON and back:
114
115```
116use sciter::Value;
117
118let mut v: Value = "[1, 2, 3, 4]".parse().unwrap();
119let json_str = v.into_string();
120```
121
122Array access:
123
124```
125use sciter::Value;
126
127let mut v: Value = "[10, 20]".parse().unwrap();
128assert_eq!(v[0], Value::from(10));
129
130// explicit arguments:
131v.set(1, Value::from(21));
132v.set(2, Value::from(22));
133
134// implicit arguments:
135v.set(1, 21);
136v.set(2, 22);
137
138assert_eq!(v.len(), 3);
139
140assert!(v.get(0).is_int());
141```
142
143Map access:
144
145```
146use sciter::Value;
147
148let mut v: Value = "{one: 1, two: 2}".parse().unwrap();
149assert_eq!(v["one"], 1.into());
150assert_eq!(v.get_item("one"), 1.into());
151assert_eq!(v[Value::from("one")], Value::from(1));
152
153v.set_item("three", 3);
154assert!(v.get_item("one").is_int());
155```
156
157.
158*/
159
160use ::{_API};
161
162use capi::sctypes::*;
163use capi::scvalue::{VALUE_UNIT_TYPE_STRING, VALUE_UNIT_TYPE_OBJECT, VALUE_UNIT_UNDEFINED};
164pub use capi::scvalue::{VALUE_RESULT, VALUE_STRING_CVT_TYPE, VALUE_TYPE};
165use capi::scvalue::VALUE;
166use ::om::IAsset;
167
168
169// TODO: `get`, `get_item` methods should return `Option<Value>`
170
171/// `sciter::value` wrapper.
172///
173/// See the [module-level](index.html) documentation.
174pub struct Value
175{
176	data: VALUE,
177	tmp: * mut Value,
178}
179
180/// `sciter::Value` can be transferred across thread boundaries.
181unsafe impl Send for Value {}
182
183impl Value {
184
185	/// Return a new Sciter value object ([`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)).
186	pub const fn new() -> Value {
187		Value { data: VALUE::new(), tmp: ::std::ptr::null_mut() }
188	}
189
190	/// Make an explicit [array](https://sciter.com/docs/content/script/Array.htm) value with the given length.
191	pub fn array(length: usize) -> Value {
192		let mut me = Value::new();
193		(_API.ValueIntDataSet)(me.as_ptr(), length as i32, VALUE_TYPE::T_ARRAY as UINT, 0);
194		return me;
195	}
196
197	/// Make an explicit [map](https://sciter.com/docs/content/script/Object.htm) value.
198	pub fn map() -> Value {
199		let mut me = Value::new();
200		(_API.ValueIntDataSet)(me.as_ptr(), 0i32, VALUE_TYPE::T_MAP as UINT, 0);
201		return me;
202	}
203
204	/// Make an explicit json [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null) value.
205	pub const fn null() -> Value {
206		let mut me = Value::new();
207		me.data.t = VALUE_TYPE::T_NULL;
208		return me;
209	}
210	/// Make an explicit `nothing` (where did it come from?).
211	pub const fn nothing() -> Value {
212		let mut me = Value::new();
213		me.data.t = VALUE_TYPE::T_UNDEFINED;
214		me.data.u = VALUE_UNIT_UNDEFINED::UT_NOTHING as UINT;
215		return me;
216	}
217
218	/// Make Sciter [symbol](https://sciter.com/docs/content/script/language/Syntax.htm#symbol-literals) value.
219	pub fn symbol(val: &str) -> Value {
220		let mut me = Value::new();
221		me.assign_str(val, VALUE_UNIT_TYPE_STRING::SYMBOL);
222		return me;
223	}
224
225	/// Make Sciter [error](https://sciter.com/docs/content/script/Error.htm) value.
226	pub fn error(val: &str) -> Value {
227		let mut me = Value::new();
228		me.assign_str(val, VALUE_UNIT_TYPE_STRING::ERROR);
229		return me;
230	}
231
232	/// Make Sciter [color](https://sciter.com/docs/content/script/Color.htm) value, in `0xAABBGGRR` form.
233	pub fn color(val: u32) -> Value {
234		let mut me = Value::new();
235		(_API.ValueIntDataSet)(me.as_ptr(), val as i32, VALUE_TYPE::T_COLOR as u32, 0);
236		return me;
237	}
238
239	/// Make Sciter [duration](https://sciter.com/docs/content/script/language/Types.htm) value, in seconds.
240	pub fn duration(val: f64) -> Value {
241		let mut me = Value::new();
242		(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_DURATION as u32, 0);
243		return me;
244	}
245
246	/// Make Sciter [angle](https://sciter.com/docs/content/script/Angle.htm) value, in radians.
247	pub fn angle(val: f64) -> Value {
248		let mut me = Value::new();
249		(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_ANGLE as u32, 0);
250		return me;
251	}
252
253	/// Parse a json string into value. Returns the number of chars left unparsed in case of error.
254	pub fn parse(val: &str) -> Result<Value, usize> {
255		return Value::parse_as(val, VALUE_STRING_CVT_TYPE::JSON_LITERAL);
256	}
257
258	/// Parse a json string into value. Returns the number of chars left unparsed in case of error.
259	pub fn parse_as(val: &str, how: VALUE_STRING_CVT_TYPE) -> Result<Value, usize> {
260		let mut me = Value::new();
261		let (s,n) = s2wn!(val);
262		let ok: u32 = (_API.ValueFromString)(me.as_ptr(), s.as_ptr(), n, how);
263		if ok == 0 {
264			Ok(me)
265		} else {
266			Err(ok as usize)
267		}
268	}
269
270	/// Value to asset.
271	pub fn to_asset<T>(&self) -> Option<&mut IAsset<T>> {
272		if self.is_asset() {
273			let mut val = 0_i64;
274			if (_API.ValueInt64Data)(self.as_cptr(), &mut val)  == VALUE_RESULT::OK {
275				let ptr = val as usize as *mut IAsset<T>;
276				let asset = unsafe { &mut *ptr };
277				return Some(asset);
278			}
279		}
280		return None;
281	}
282
283	/// Returns a raw pointer to the underlaying data.
284	pub fn as_mut_ptr(&mut self) -> *mut VALUE {
285		&mut self.data as *mut VALUE
286	}
287
288	#[doc(hidden)]
289	pub fn as_ptr(&mut self) -> *mut VALUE {
290		&mut self.data as *mut VALUE
291	}
292
293	#[doc(hidden)]
294	pub fn as_cptr(&self) -> *const VALUE {
295		&self.data as *const VALUE
296	}
297
298	/// Get the inner type of the value.
299	pub const fn get_type(&self) -> VALUE_TYPE {
300		return self.data.t;
301	}
302
303	/// Get the inner type and its subtype (e.g. units) of the value.
304	pub const fn full_type(&self) -> (VALUE_TYPE, UINT) {
305		return (self.data.t, self.data.u);
306	}
307
308	/// Convert `T_OBJECT` value type to JSON `T_MAP` or `T_ARRAY` types.
309	///
310	/// Also must be used if you need to pass values between different threads.
311	pub fn isolate(&mut self) {
312		(_API.ValueIsolate)(self.as_ptr());
313	}
314
315	/// Clear the value. It deallocates all assosiated structures that are not used anywhere else.
316	pub fn clear(&mut self) -> &mut Value {
317		(_API.ValueClear)(self.as_ptr());
318		self
319	}
320
321	/// Return the number of items in the `T_ARRAY`, `T_MAP`, `T_FUNCTION` and `T_OBJECT` value types.
322	pub fn len(&self) -> usize {
323		let mut n: INT = 0;
324		(_API.ValueElementsCount)(self.as_cptr(), &mut n);
325		return n as usize;
326	}
327
328	/// Append another value to the end of `T_ARRAY` value.
329	pub fn push<T: Into<Value>>(&mut self, src: T) {
330		(_API.ValueNthElementValueSet)(self.as_ptr(), self.len() as INT, src.into().as_cptr());
331	}
332
333	/// Insert or set value at the given `index` of `T_ARRAY`, `T_MAP`, `T_FUNCTION` and `T_OBJECT` value.
334	pub fn set<T: Into<Value>>(&mut self, index: usize, src: T) {
335		(_API.ValueNthElementValueSet)(self.as_ptr(), index as INT, src.into().as_cptr());
336	}
337
338	/// Retreive value of sub-element at `index`.
339	///
340	/// * `T_ARRAY` - nth element of the array;
341	/// * `T_MAP` - value of the nth key/value pair in the map;
342	/// * `T_FUNCTION` - value of the nth argument of the function.
343	///
344	pub fn get(&self, index: usize) -> Value {
345		let mut v = Value::new();
346		(_API.ValueNthElementValue)(self.as_cptr(), index as INT, v.as_ptr());
347		return v;
348	}
349
350	/// Insert or set value of the sub-element by `key`.
351	///
352	/// * `T_MAP` - sets named value in the map;
353	/// * `T_OBJECT` - sets value of property of the object;
354	/// * `T_FUNCTION` - sets named argument of the function;
355	/// * otherwise it converts self to the map type and adds the key/value to it.
356	///
357	pub fn set_item<TKey: Into<Value>, TValue: Into<Value>>(&mut self, key: TKey, value: TValue) {
358		(_API.ValueSetValueToKey)(self.as_ptr(), key.into().as_cptr(), value.into().as_cptr());
359	}
360
361	/// Retrieve the value of a sub-element by key.
362	pub fn get_item<T: Into<Value>>(&self, key: T) -> Value {
363		let mut v = Value::new();
364		(_API.ValueGetValueOfKey)(self.as_cptr(), key.into().as_cptr(), v.as_ptr());
365		return v;
366	}
367
368	/// Retrieve the key of a sub-element by `index`.
369	pub fn key_at(&self, index: usize) -> Value {
370		let mut v = Value::new();
371		(_API.ValueNthElementKey)(self.as_cptr(), index as INT, v.as_ptr());
372		return v;
373	}
374
375	/// An iterator visiting all keys of key/value pairs in the map.
376	///
377	/// * `T_MAP` - keys of key/value pairs in the map;
378	/// * `T_OBJECT` - names of key/value properties in the object;
379	/// * `T_FUNCTION` - names of arguments of the function (if any).
380	///
381  /// The iterator element type is `Value` (as a key).
382	pub fn keys(&self) -> KeyIterator {
383		KeyIterator {
384			base: self,
385			index: 0,
386			count: self.len(),
387		}
388	}
389
390	/// An iterator visiting all values in arbitrary order.
391	///
392	/// * `T_ARRAY` - elements of the array;
393	/// * `T_MAP` - values of key/value pairs in the map;
394	/// * `T_OBJECT` - values of key/value properties in the object;
395	/// * `T_FUNCTION` - values of arguments of the function.
396	///
397  /// The iterator element type is `Value`.
398	pub fn values(&self) -> SeqIterator {
399		SeqIterator {
400			base: self,
401			index: 0,
402			count: self.len(),
403		}
404	}
405
406	/// An iterator visiting all key-value pairs in arbitrary order.
407	///
408  /// The `Value` must has a key-value type (map, object, function).
409  ///
410	/// The iterator element type is `(Value, Value)`.
411	pub fn items(&self) -> Vec<(Value, Value)> {
412		type VecType = Vec<(Value, Value)>;
413		let mut result = Vec::with_capacity(self.len());
414
415		extern "system" fn on_pair(param: LPVOID, pkey: *const VALUE, pval: *const VALUE) -> BOOL {
416			assert!(!param.is_null());
417			unsafe {
418				let result = param as *mut VecType;
419				let result = &mut *result;
420				let item = (Value::copy_from(pkey), Value::copy_from(pval));
421				result.push(item);
422			}
423			return true as BOOL;
424		}
425
426		let ptr = &mut result as *mut VecType;
427		(_API.ValueEnumElements)(self.as_cptr(), on_pair, ptr as LPVOID);
428
429		return result;
430	}
431
432	/// Value to integer.
433	pub fn to_int(&self) -> Option<i32> {
434		let mut val = 0i32;
435		match (_API.ValueIntData)(self.as_cptr(), &mut val) {
436			VALUE_RESULT::OK => Some(val),
437			_ => None
438		}
439	}
440
441	/// Value to bool.
442	pub fn to_bool(&self) -> Option<bool> {
443		let mut val = 0i32;
444		match (_API.ValueIntData)(self.as_cptr(), &mut val) {
445			VALUE_RESULT::OK => Some(val != 0),
446			_ => None
447		}
448	}
449
450	/// Value to float.
451	pub fn to_float(&self) -> Option<f64> {
452		let mut val = 0f64;
453		match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
454			VALUE_RESULT::OK => Some(val),
455			_ => None
456		}
457	}
458
459	/// Value to color.
460	pub fn to_color(&self) -> Option<u32> {
461		let mut val = 0i32;
462		match (_API.ValueIntData)(self.as_cptr(), &mut val) {
463			VALUE_RESULT::OK => Some(val as u32),
464			_ => None
465		}
466	}
467
468	/// Value to duration.
469	pub fn to_duration(&self) -> Option<f64> {
470		let mut val = 0f64;
471		match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
472			VALUE_RESULT::OK => Some(val),
473			_ => None
474		}
475	}
476
477	/// Value to angle.
478	pub fn to_angle(&self) -> Option<f64> {
479		let mut val = 0f64;
480		match (_API.ValueFloatData)(self.as_cptr(), &mut val) {
481			VALUE_RESULT::OK => Some(val),
482			_ => None
483		}
484	}
485
486	/// Value as string for `T_STRING` type.
487	pub fn as_string(&self) -> Option<String> {
488		let mut s = 0 as LPCWSTR;
489		let mut n = 0_u32;
490		match (_API.ValueStringData)(self.as_cptr(), &mut s, &mut n) {
491			VALUE_RESULT::OK => Some(::utf::w2sn(s, n as usize)),
492			_ => None
493		}
494	}
495
496	/// Value to json string (converted in-place). _Subject to change._
497	pub fn into_string(mut self) -> String {
498		(_API.ValueToString)(self.as_ptr(), VALUE_STRING_CVT_TYPE::JSON_LITERAL);
499		return self.as_string().unwrap();
500	}
501
502	/// Value as a byte slice for `T_BYTES` type.
503	pub fn as_bytes(&self) -> Option<&[u8]> {
504		let mut s = 0 as LPCBYTE;
505		let mut n = 0_u32;
506		match (_API.ValueBinaryData)(self.as_cptr(), &mut s, &mut n) {
507			VALUE_RESULT::OK => Some(unsafe { ::std::slice::from_raw_parts(s, n as usize) }),
508			_ => None
509		}
510	}
511
512	/// Value to byte vector for `T_BYTES` type.
513	pub fn to_bytes(&self) -> Option<Vec<u8>> {
514		self.as_bytes().map(ToOwned::to_owned)
515	}
516
517	/// Function invocation for `T_OBJECT` with `UT_OBJECT_FUNCTION` value type.
518	///
519	/// Calls the tiscript function or method holded at `Value` with context of `this` object
520	/// that will be known as _this_ inside that function (it is optional for global functions).
521	///
522	/// The `name` here is an url or a name of the script - used for error reporting in script.
523	///
524	/// You can use the [`make_args!(args...)`](../macro.make_args.html) macro which helps you
525	/// to construct script arguments from Rust types.
526	pub fn call(&self, this: Option<Value>, args: &[Value], name: Option<&str>) -> Result<Value, VALUE_RESULT> {
527		let mut rv = Value::new();
528		let argv = Value::pack_args(args);
529		let name = s2w!(name.unwrap_or(""));
530		let ok = (_API.ValueInvoke)(self.as_cptr(), this.unwrap_or_default().as_ptr(),
531			argv.len() as UINT, argv.as_ptr(), rv.as_ptr(), name.as_ptr());
532		match ok {
533			VALUE_RESULT::OK => Ok(rv),
534			_ => Err(ok)
535		}
536	}
537
538	#[doc(hidden)]
539	pub fn pack_to(&self, dst: &mut VALUE) {
540		(_API.ValueCopy)(dst, self.as_cptr());
541	}
542
543	#[doc(hidden)]
544	pub fn pack_args(args: &[Value]) -> Vec<VALUE> {
545		let argc = args.len();
546		let mut argv: Vec<VALUE> = Vec::with_capacity(argc);
547		argv.resize(argc, VALUE::default());
548		for i in 0..argc {
549			args[i].pack_to(&mut argv[i]);
550		}
551		return argv;
552	}
553
554	#[doc(hidden)]
555	pub unsafe fn unpack_from(args: * const VALUE, count: UINT) -> Vec<Value> {
556		let argc = count as usize;
557		let mut argv: Vec<Value> = Vec::with_capacity(argc);
558		assert!(argc == 0 || !args.is_null());
559		let args = ::std::slice::from_raw_parts(args, argc);
560		for arg in args {
561			argv.push(Value::copy_from(arg));
562		}
563		return argv;
564	}
565
566	#[doc(hidden)]
567	unsafe fn copy_from(ptr: *const VALUE) -> Value {
568		assert!(!ptr.is_null());
569		let mut v = Value::new();
570		(_API.ValueCopy)(v.as_ptr(), ptr);
571		return v;
572	}
573
574  #[allow(clippy::mut_from_ref)]
575	fn ensure_tmp_mut(&self) -> &mut Value {
576		let cp = self as *const Value;
577		let mp = cp as *mut Value;
578		let me = unsafe { &mut *mp };
579		return me.ensure_tmp();
580	}
581
582	fn ensure_tmp(&mut self) -> &mut Value {
583		if self.tmp.is_null() {
584			let tmp = Box::new(Value::new());
585			self.tmp = Box::into_raw(tmp);
586		}
587		return unsafe { &mut *self.tmp };
588	}
589
590	/// Returns `true` is `self` is `undefined` or has zero elements.
591	pub fn is_empty(&self) -> bool {
592		self.is_undefined() || self.len() == 0
593	}
594
595	#[allow(missing_docs)]
596	pub const fn is_undefined(&self) -> bool {
597		self.data.t as u32 == VALUE_TYPE::T_UNDEFINED as u32 && self.data.u == 0
598	}
599	#[allow(missing_docs)]
600	pub const fn is_null(&self) -> bool {
601		self.data.t as u32 == VALUE_TYPE::T_NULL as u32
602	}
603	#[allow(missing_docs)]
604	pub const fn is_nothing(&self) -> bool {
605		self.data.t as u32 == VALUE_TYPE::T_UNDEFINED as u32 && self.data.u == VALUE_UNIT_UNDEFINED::UT_NOTHING as UINT
606	}
607	#[allow(missing_docs)]
608	pub const fn is_bool(&self) -> bool {
609		self.data.t as u32 == VALUE_TYPE::T_BOOL as u32
610	}
611	#[allow(missing_docs)]
612	pub const fn is_int(&self) -> bool {
613		self.data.t as u32 == VALUE_TYPE::T_INT as u32
614	}
615	#[allow(missing_docs)]
616	pub const fn is_float(&self) -> bool {
617		self.data.t as u32 == VALUE_TYPE::T_FLOAT as u32
618	}
619	#[allow(missing_docs)]
620	pub const fn is_bytes(&self) -> bool {
621		self.data.t as u32 == VALUE_TYPE::T_BYTES as u32
622	}
623	#[allow(missing_docs)]
624	pub const fn is_string(&self) -> bool {
625		self.data.t as u32 == VALUE_TYPE::T_STRING as u32
626	}
627	#[allow(missing_docs)]
628	pub const fn is_symbol(&self) -> bool {
629		self.data.t as u32 == VALUE_TYPE::T_STRING as u32 && self.data.u == VALUE_UNIT_TYPE_STRING::SYMBOL as UINT
630	}
631	#[allow(missing_docs)]
632	pub const fn is_error_string(&self) -> bool {
633		self.data.t as u32 == VALUE_TYPE::T_STRING as u32 && self.data.u == VALUE_UNIT_TYPE_STRING::ERROR as UINT
634	}
635	#[allow(missing_docs)]
636	pub const fn is_date(&self) -> bool {
637		self.data.t as u32 == VALUE_TYPE::T_DATE as u32
638	}
639	#[allow(missing_docs)]
640	pub const fn is_currency(&self) -> bool {
641		self.data.t as u32 == VALUE_TYPE::T_CURRENCY as u32
642	}
643	#[allow(missing_docs)]
644	pub const fn is_color(&self) -> bool {
645		self.data.t as u32 == VALUE_TYPE::T_COLOR as u32
646	}
647	#[allow(missing_docs)]
648	pub const fn is_duration(&self) -> bool {
649		self.data.t as u32 == VALUE_TYPE::T_DURATION as u32
650	}
651	#[allow(missing_docs)]
652	pub const fn is_angle(&self) -> bool {
653		self.data.t as u32 == VALUE_TYPE::T_ANGLE as u32
654	}
655	#[allow(missing_docs)]
656	pub const fn is_map(&self) -> bool {
657		self.data.t as u32 == VALUE_TYPE::T_MAP as u32
658	}
659	#[allow(missing_docs)]
660	pub const fn is_array(&self) -> bool {
661		self.data.t as u32 == VALUE_TYPE::T_ARRAY as u32
662	}
663	#[allow(missing_docs)]
664	pub const fn is_function(&self) -> bool {
665		self.data.t as u32 == VALUE_TYPE::T_FUNCTION as u32
666	}
667	#[allow(missing_docs)]
668	pub fn is_native_function(&self) -> bool {
669		(_API.ValueIsNativeFunctor)(self.as_cptr()) != 0
670	}
671	#[allow(missing_docs)]
672	pub const fn is_object(&self) -> bool {
673		self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32
674	}
675	#[allow(missing_docs)]
676	pub const fn is_asset(&self) -> bool {
677		self.data.t as u32 == VALUE_TYPE::T_ASSET as u32
678	}
679
680	/// I.e. non-reference types that do not need a destructor.
681	pub const fn is_primitive(&self) -> bool {
682		use capi::scvalue::VALUE_TYPE::*;
683		matches!(self.data.t,
684			T_UNDEFINED
685			| T_NULL
686			| T_BOOL
687			| T_INT
688			| T_FLOAT
689			| T_DATE
690		)
691	}
692
693  // script types:
694  #[allow(missing_docs)]
695  pub const fn is_object_array(&self) -> bool {
696    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::ARRAY as UINT
697  }
698  #[allow(missing_docs)]
699  pub const fn is_object_map(&self) -> bool {
700    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::OBJECT as UINT
701  }
702  #[allow(missing_docs)]
703  pub const fn is_object_class(&self) -> bool {
704    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::OBJECT as UINT
705  }
706  #[allow(missing_docs)]
707  pub const fn is_object_native(&self) -> bool {
708    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::NATIVE as UINT
709  }
710  #[allow(missing_docs)]
711  pub const fn is_object_function(&self) -> bool {
712    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::FUNCTION as UINT
713  }
714  #[allow(missing_docs)]
715  pub const fn is_object_error(&self) -> bool {
716    self.data.t as u32 == VALUE_TYPE::T_OBJECT as u32 && self.data.u == VALUE_UNIT_TYPE_OBJECT::ERROR as UINT
717  }
718	#[allow(missing_docs)]
719	pub const fn is_dom_element(&self) -> bool {
720		self.data.t as u32 == VALUE_TYPE::T_DOM_OBJECT as u32
721	}
722
723  // generic check (native or object):
724  #[allow(missing_docs)]
725  pub const fn is_varray(&self) -> bool {
726    self.is_array() || self.is_object()
727  }
728  #[allow(missing_docs)]
729  pub const fn is_vmap(&self) -> bool {
730    self.is_map() || self.is_object_map()
731  }
732  #[allow(missing_docs)]
733  pub fn is_vfunction(&self) -> bool {
734    self.is_function() || self.is_object_function() || self.is_native_function()
735  }
736  #[allow(missing_docs)]
737  pub const fn is_verror(&self) -> bool {
738    self.is_error_string() || self.is_object_error()
739  }
740
741	fn assign_str(&mut self, val: &str, unit: VALUE_UNIT_TYPE_STRING) -> VALUE_RESULT {
742		let (s,n) = s2wn!(val);
743		return (_API.ValueStringDataSet)(self.as_ptr(), s.as_ptr(), n, unit as UINT);
744	}
745}
746
747
748/// Print `Value` as json string
749impl ::std::fmt::Display for Value {
750	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
751		let copy = self.clone();
752		let re = copy.into_string();
753		f.write_str(&re)
754	}
755}
756
757/// Print `Value` as json string with explicit type showed.
758impl ::std::fmt::Debug for Value {
759	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
760
761		let mut tname = format!("{:?}", self.data.t);
762
763		if self.is_undefined() || self.is_null() {
764			return f.write_str(&tname[2..].to_lowercase());
765
766		} else if self.is_nothing() {
767			return f.write_str("nothing");
768
769		} else if self.is_string() && self.data.u != 0 {
770			// VALUE_UNIT_TYPE_STRING
771			let units = [
772				("file", 0xfffe), ("symbol", 0xffff),
773				("string", 0), ("error", 1), ("secure", 2),
774				("url", 3), ("selector", 4),
775				];
776
777			tname.push(':');
778			if let Some(name) = units.iter().find(|&&x| x.1 == self.data.u) {
779				tname.push_str(name.0);
780			} else {
781				tname.push_str(&self.data.u.to_string());
782			}
783
784		} else if self.is_object() {
785			// VALUE_UNIT_TYPE_OBJECT
786			let units = ["array", "object", "class", "native", "function", "error"];
787			let u = self.data.u as usize;
788			tname.push(':');
789			if u < units.len() {
790				tname.push_str(units[u]);
791			} else {
792				tname.push_str(&u.to_string());
793			}
794
795		} else if self.data.u != 0 {
796			// VALUE_UNIT_TYPE
797			// redundant? like "length:7:12px" instead of "length:12px" (7 == `UT_PX`).
798
799			// tname.push_str(":");
800			// tname.push_str(&self.data.u.to_string());
801		}
802		f.write_str(&tname[2..].to_lowercase())?;
803		f.write_str(":")?;
804		write!(f, "{}", &self)
805	}
806}
807
808/// Destroy pointed value.
809impl Drop for Value {
810	fn drop(&mut self) {
811		// drop the attached side-data if any.
812		if !self.tmp.is_null() {
813			let _drop_tmp = unsafe { Box::from_raw(self.tmp) };
814		}
815		if std::thread::panicking() {
816			// it is fine to do nothing for the non-reference types.
817			if self.is_primitive() {
818				return;
819			}
820			// well, if we're panicking, expect a recursive panic here :(
821		}
822		(_API.ValueClear)(self.as_ptr());
823	}
824}
825
826/// Return default value (`undefined`).
827impl Default for Value {
828	fn default() -> Self {
829		return Value::new();
830	}
831}
832
833/// Copies value.
834///
835/// All allocated objects are reference counted so copying is just a matter of increasing reference counts.
836impl Clone for Value {
837	fn clone(&self) -> Self {
838		let mut dst = Value::new();
839		(_API.ValueCopy)(dst.as_ptr(), self.as_cptr());
840		return dst;
841	}
842}
843
844/// Compare two values.
845impl ::std::cmp::PartialEq for Value {
846	fn eq(&self, other: &Self) -> bool {
847		let eq = (_API.ValueCompare)(self.as_cptr(), other.as_cptr());
848		matches!(eq, VALUE_RESULT::OK_TRUE)
849	}
850}
851
852/// Get item by index for array type.
853impl ::std::ops::Index<usize> for Value {
854	type Output = Value;
855	fn index(&self, index: usize) -> &Self::Output {
856		let tmp = self.ensure_tmp_mut();
857		(_API.ValueNthElementValue)(self.as_cptr(), index as INT, tmp.as_ptr());
858		return tmp;
859	}
860}
861
862/// Set item by index for array type.
863#[cfg(notworking)]
864impl ::std::ops::IndexMut<usize> for Value {
865	fn index_mut(&mut self, index: usize) -> &mut Value {
866		let tmp = self.ensure_tmp_mut();
867		(_API.ValueNthElementValue)(self.as_cptr(), index as INT, tmp.as_ptr());
868		return tmp;
869	}
870}
871
872/// Get item by key for map type.
873impl ::std::ops::Index<Value> for Value {
874	type Output = Value;
875	fn index(&self, key: Value) -> &Self::Output {
876		let tmp = self.ensure_tmp_mut();
877		(_API.ValueGetValueOfKey)(self.as_cptr(), key.as_cptr(), tmp.as_ptr());
878		return tmp;
879	}
880}
881
882/// Get item by string key for map type.
883impl ::std::ops::Index<&'static str> for Value {
884	type Output = Value;
885	fn index(&self, key: &'static str) -> &Self::Output {
886		let tmp = self.ensure_tmp_mut();
887		(_API.ValueGetValueOfKey)(self.as_cptr(), Value::from(key).as_cptr(), tmp.as_ptr());
888		return tmp;
889	}
890}
891
892/// Set item by key for map type.
893#[cfg(notworking)]
894impl ::std::ops::IndexMut<Value> for Value {
895	fn index_mut<'a>(&'a mut self, key: Value) -> &'a mut Value {
896		let ptr = self.as_ptr();
897		let tmp = self.ensure_tmp();
898		(_API.ValueSetValueToKey)(ptr, key.as_cptr(), tmp.as_ptr());
899		return tmp;
900	}
901}
902
903/// Value from nothing (`()`) for empty return values.
904///
905/// Returns `undefined` value.
906impl From<()> for Value {
907	fn from(_: ()) -> Self {
908		Value::new()
909	}
910}
911
912/// Value from a native `VALUE` object.
913impl<'a> From<&'a VALUE> for Value {
914  fn from(val: &'a VALUE) -> Self {
915    unsafe { Value::copy_from(val as *const _) }
916  }
917}
918
919/// Value from integer.
920impl From<i32> for Value {
921	// Note that there is no generic 64-bit integers at Sciter, only Date/Currency types.
922	// There is a double (f64) for large numbers as a workaround.
923	fn from(val: i32) -> Self {
924		let mut me = Value::new();
925		(_API.ValueIntDataSet)(me.as_ptr(), val, VALUE_TYPE::T_INT as UINT, 0);
926		return me;
927	}
928}
929
930/// Value from integer.
931impl From<&i32> for Value {
932	// Note that there is no generic 64-bit integers at Sciter, only Date/Currency types.
933	// There is a double (f64) for large numbers as a workaround.
934	fn from(val: &i32) -> Self {
935		let mut me = Value::new();
936		(_API.ValueIntDataSet)(me.as_ptr(), *val, VALUE_TYPE::T_INT as UINT, 0);
937		return me;
938	}
939}
940
941/// Value from float.
942impl From<f64> for Value {
943	fn from(val: f64) -> Self {
944		let mut me = Value::new();
945		(_API.ValueFloatDataSet)(me.as_ptr(), val, VALUE_TYPE::T_FLOAT as UINT, 0);
946		return me;
947	}
948}
949
950/// Value from float.
951impl From<&f64> for Value {
952	fn from(val: &f64) -> Self {
953		let mut me = Value::new();
954		(_API.ValueFloatDataSet)(me.as_ptr(), *val, VALUE_TYPE::T_FLOAT as UINT, 0);
955		return me;
956	}
957}
958
959/// Value from bool.
960impl From<bool> for Value {
961	fn from(val: bool) -> Self {
962		let mut me = Value::new();
963		(_API.ValueIntDataSet)(me.as_ptr(), val as INT, VALUE_TYPE::T_BOOL as UINT, 0);
964		return me;
965	}
966}
967
968/// Value from bool.
969impl From<&bool> for Value {
970	fn from(val: &bool) -> Self {
971		let mut me = Value::new();
972		(_API.ValueIntDataSet)(me.as_ptr(), *val as INT, VALUE_TYPE::T_BOOL as UINT, 0);
973		return me;
974	}
975}
976
977/// Value from string.
978impl<'a> From<&'a str> for Value {
979	fn from(val: &'a str) -> Self {
980		let mut me = Value::new();
981		me.assign_str(val, VALUE_UNIT_TYPE_STRING::STRING);
982		return me;
983	}
984}
985
986/// Value from string.
987impl From<String> for Value {
988	fn from(val: String) -> Self {
989		let mut me = Value::new();
990		me.assign_str(&val, VALUE_UNIT_TYPE_STRING::STRING);
991		return me;
992	}
993}
994
995impl<'a> From<&'a String> for Value {
996	fn from(val: &'a String) -> Self {
997		let mut me = Value::new();
998		me.assign_str(val, VALUE_UNIT_TYPE_STRING::STRING);
999		return me;
1000	}
1001}
1002
1003/// Value from json string.
1004impl ::std::str::FromStr for Value {
1005	type Err = VALUE_RESULT;
1006	fn from_str(val: &str) -> Result<Self, Self::Err> {
1007		Value::parse(val).or(Err(VALUE_RESULT::BAD_PARAMETER))
1008	}
1009}
1010
1011/// Value from binary array (sequence of bytes).
1012impl<'a> From<&'a [u8]> for Value {
1013	fn from(val: &'a [u8]) -> Self {
1014		let mut me = Value::new();
1015		(_API.ValueBinaryDataSet)(me.as_ptr(), val.as_ptr(), val.len() as UINT, VALUE_TYPE::T_BYTES as UINT, 0);
1016		return me;
1017	}
1018}
1019
1020/// Value from time/date.
1021impl From<std::time::SystemTime> for Value {
1022	/// See the [VALUE_TIME::T_DATE].
1023	fn from(val: std::time::SystemTime) -> Self {
1024		let mut me = Value::new();
1025		if let Ok(epoch) = val.duration_since(std::time::UNIX_EPOCH) {
1026			// in 100ns from epoch
1027			let ns = epoch.as_nanos() / 100;
1028
1029			// does not fail because does not check the input
1030			// TODO: is SystemTime UTC or not?
1031			(_API.ValueInt64DataSet)(me.as_ptr(), ns as i64, VALUE_TYPE::T_DATE as u32, 0);
1032		}
1033		me
1034	}
1035}
1036
1037/// Value from [`Result`].
1038impl<T, E> From<Result<T, E>> for Value where T: Into<Value>, E: std::fmt::Display {
1039	fn from(val: Result<T, E>) -> Self {
1040		match val {
1041			Ok(v) => v.into(),
1042			Err(e) => Value::error(&e.to_string()),
1043		}
1044	}
1045}
1046
1047// /// Value from sequence of items satisfying `Into<Value>`.
1048// impl ::std::iter::FromIterator<Into<Value>> for Value {
1049//   fn from_iter<I: IntoIterator<Item=Into<Value>>>(iterator: I) -> Self {
1050//     let iterator = iterator.into_iter();
1051//     let capacity = iterator.size_hint().0;
1052//     let mut v = Value::array(capacity);
1053//     for i in iterator {
1054//       v.push(Value::from(i));
1055//     }
1056//     return v;
1057//   }
1058// }
1059
1060/// Value from sequence of `Value`.
1061impl ::std::iter::FromIterator<Value> for Value {
1062  fn from_iter<I: IntoIterator<Item=Value>>(iterator: I) -> Self {
1063    let iterator = iterator.into_iter();
1064    let capacity = iterator.size_hint().0;
1065    let mut v = Value::array(capacity);
1066    for (i, m) in iterator.enumerate() {
1067      v.set(i, m);
1068    }
1069    return v;
1070  }
1071}
1072
1073/// Value from sequence of `i32`.
1074impl ::std::iter::FromIterator<i32> for Value {
1075	fn from_iter<I: IntoIterator<Item=i32>>(iterator: I) -> Self {
1076    let iterator = iterator.into_iter();
1077    let capacity = iterator.size_hint().0;
1078		let mut v = Value::array(capacity);
1079    for (i, m) in iterator.enumerate() {
1080      v.set(i, Value::from(m));
1081		}
1082		return v;
1083	}
1084}
1085
1086/// Value from sequence of `f64`.
1087impl ::std::iter::FromIterator<f64> for Value {
1088	fn from_iter<I: IntoIterator<Item=f64>>(iterator: I) -> Self {
1089    let iterator = iterator.into_iter();
1090    let capacity = iterator.size_hint().0;
1091    let mut v = Value::array(capacity);
1092    for (i, m) in iterator.enumerate() {
1093      v.set(i, Value::from(m));
1094		}
1095		return v;
1096	}
1097}
1098
1099/// Value from sequence of `&str`.
1100impl<'a> ::std::iter::FromIterator<&'a str> for Value {
1101	fn from_iter<I: IntoIterator<Item=&'a str>>(iterator: I) -> Self {
1102    let iterator = iterator.into_iter();
1103    let capacity = iterator.size_hint().0;
1104    let mut v = Value::array(capacity);
1105    for (i, m) in iterator.enumerate() {
1106      v.set(i, Value::from(m));
1107		}
1108		return v;
1109	}
1110}
1111
1112/// Value from sequence of `String`.
1113impl ::std::iter::FromIterator<String> for Value {
1114	fn from_iter<I: IntoIterator<Item=String>>(iterator: I) -> Self {
1115    let iterator = iterator.into_iter();
1116    let capacity = iterator.size_hint().0;
1117    let mut v = Value::array(capacity);
1118    for (i, m) in iterator.enumerate() {
1119      v.set(i, Value::from(m));
1120		}
1121		return v;
1122	}
1123}
1124
1125/// Value from function.
1126impl<F, R> From<F> for Value
1127where
1128	F: Fn(&[Value]) -> R,
1129	R: Into<Value>,
1130{
1131	fn from(f: F) -> Value {
1132		let mut v = Value::new();
1133		let boxed = Box::new(f);
1134		let ptr = Box::into_raw(boxed);	// dropped in `_functor_release`
1135		(_API.ValueNativeFunctorSet)(v.as_ptr(), _functor_invoke::<F,R>, _functor_release::<F>, ptr as LPVOID);
1136		return v;
1137	}
1138}
1139
1140/// Value from asset.
1141impl<T> From<Box<IAsset<T>>> for Value {
1142	fn from(ptr: Box<IAsset<T>>) -> Value {
1143		let ptr = Box::into_raw(ptr);
1144		let mut me = Value::new();
1145		(_API.ValueInt64DataSet)(me.as_ptr(), ptr as usize as i64, VALUE_TYPE::T_ASSET as u32, 0);
1146		return me;
1147	}
1148}
1149
1150extern "C" fn _functor_release<F>(tag: LPVOID)
1151{
1152	// reconstruct handler from pointer
1153	let ptr = tag as *mut F;
1154	let boxed = unsafe { Box::from_raw(ptr) };
1155	// and forget it
1156	drop(boxed);
1157}
1158
1159extern "C" fn _functor_invoke<F, R>(tag: LPVOID, argc: UINT, argv: *const VALUE, retval: *mut VALUE)
1160where
1161	F: Fn(&[Value]) -> R,
1162	R: Into<Value>,
1163{
1164	// reconstruct handler from pointer
1165	let ptr = tag as *mut F;
1166	let me = unsafe { &mut *ptr };
1167	let retval = unsafe { &mut *retval };
1168	let args = unsafe { Value::unpack_from(argv, argc) };
1169	let rv = me(&args);
1170	let rv: Value = rv.into();
1171	rv.pack_to(retval)
1172}
1173
1174
1175/// Helper trait
1176pub trait FromValue {
1177	/// Converts value to specified type.
1178	fn from_value(v: &Value) -> Option<Self> where Self: Sized;
1179}
1180
1181impl FromValue for Value {
1182	fn from_value(v: &Value) -> Option<Self> {
1183		Some(v.clone())
1184	}
1185}
1186
1187impl FromValue for bool {
1188	fn from_value(v: &Value) -> Option<Self> {
1189		v.to_bool()
1190	}
1191}
1192
1193impl FromValue for i32 {
1194	fn from_value(v: &Value) -> Option<Self> {
1195		v.to_int()
1196	}
1197}
1198
1199impl FromValue for f64 {
1200	fn from_value(v: &Value) -> Option<Self> {
1201		v.to_float()
1202	}
1203}
1204
1205impl FromValue for Vec<u8> {
1206	fn from_value(v: &Value) -> Option<Self> {
1207		v.to_bytes()
1208	}
1209}
1210
1211impl FromValue for String {
1212	fn from_value(v: &Value) -> Option<Self> {
1213		v.as_string()
1214	}
1215}
1216
1217
1218/// An iterator visiting all keys of key/value pairs in the map-like `Value` objects.
1219#[doc(hidden)]
1220pub struct KeyIterator<'a> {
1221	base: &'a Value,
1222	index: usize,
1223	count: usize,
1224}
1225
1226impl<'a> ::std::iter::Iterator for KeyIterator<'a> {
1227	type Item = Value;
1228
1229	fn next(&mut self) -> Option<Self::Item> {
1230		if self.index < self.count {
1231			self.index += 1;
1232			Some(self.base.key_at(self.index - 1))
1233		} else {
1234			None
1235		}
1236	}
1237
1238	fn size_hint(&self) -> (usize, Option<usize>) {
1239		let remain = self.count - self.index;
1240		(remain, Some(remain))
1241	}
1242
1243	fn count(self) -> usize {
1244		self.count
1245	}
1246}
1247
1248/// An iterator able to yield keys from both `Value`'s ends.
1249impl<'a> ::std::iter::DoubleEndedIterator for KeyIterator<'a> {
1250	fn next_back(&mut self) -> Option<Self::Item> {
1251		if self.index == self.count || self.count == 0 {
1252			None
1253		} else {
1254			self.count -= 1;
1255			Some(self.base.key_at(self.count))
1256		}
1257	}
1258}
1259
1260
1261/// An iterator over the sub-elements of a `Value`.
1262#[doc(hidden)]
1263pub struct SeqIterator<'a> {
1264	base: &'a Value,
1265	index: usize,
1266	count: usize,
1267}
1268
1269impl<'a> ::std::iter::Iterator for SeqIterator<'a> {
1270	type Item = Value;
1271
1272	fn next(&mut self) -> Option<Self::Item> {
1273		if self.index < self.count {
1274			self.index += 1;
1275			Some(self.base.get(self.index - 1))
1276		} else {
1277			None
1278		}
1279	}
1280
1281	fn size_hint(&self) -> (usize, Option<usize>) {
1282		let remain = self.count - self.index;
1283		(remain, Some(remain))
1284	}
1285
1286	fn count(self) -> usize {
1287		self.count
1288	}
1289}
1290
1291/// An iterator able to yield sub-elements from both `Value`'s ends.
1292impl<'a> ::std::iter::DoubleEndedIterator for SeqIterator<'a> {
1293	fn next_back(&mut self) -> Option<Self::Item> {
1294		if self.index == self.count || self.count == 0 {
1295			None
1296		} else {
1297			self.count -= 1;
1298			Some(self.base.get(self.count))
1299		}
1300	}
1301}
1302
1303/// Conversion into an `Iterator`.
1304///
1305/// Adds the `for` loop syntax support: `for subitem in &value {]`.
1306impl<'a> ::std::iter::IntoIterator for &'a Value {
1307	type Item = Value;
1308	type IntoIter = SeqIterator<'a>;
1309
1310	fn into_iter(self) -> Self::IntoIter {
1311		self.values()
1312	}
1313}
1314
1315
1316#[cfg(test)]
1317mod tests {
1318	#![allow(unused_imports)]
1319
1320	use super::{Value, FromValue};
1321	use capi::scvalue::{VALUE, VALUE_TYPE};
1322	use std::mem;
1323	use ::{_API};
1324
1325	fn check1(a: i32) {
1326		assert_eq!(a, 12);
1327	}
1328
1329	#[test]
1330	fn test_from_value() {
1331		let v = Value::from(12);
1332		check1(
1333			match FromValue::from_value(&v) {
1334				Some(x) => { x },
1335				None => { return; }
1336			}
1337		);
1338	}
1339
1340	#[test]
1341	fn test_value_layout() {
1342		assert_eq!(mem::size_of::<VALUE_TYPE>(), 4);
1343		assert_eq!(mem::size_of::<VALUE>(), 16);
1344	}
1345
1346	#[test]
1347	fn test_abi() {
1348
1349		let mut data = VALUE { t: VALUE_TYPE::T_UNDEFINED, u: 0, d: 0 };
1350		assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
1351
1352		(_API.ValueInit)(&mut data);
1353		assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
1354
1355		(_API.ValueClear)(&mut data);
1356		assert_eq!(data.t, VALUE_TYPE::T_UNDEFINED);
1357	}
1358}