mini_v8/
array.rs

1use crate::*;
2use std::fmt;
3use std::marker::PhantomData;
4
5#[derive(Clone)]
6pub struct Array {
7    pub(crate) mv8: MiniV8,
8    pub(crate) handle: v8::Global<v8::Array>,
9}
10
11impl Array {
12    /// Consumes the array and downgrades it to a JavaScript object.
13    pub fn into_object(self) -> Object {
14        self.mv8.clone().scope(|scope| {
15            let object: v8::Local<v8::Object> = v8::Local::new(scope, self.handle.clone()).into();
16            Object {
17                mv8: self.mv8,
18                handle: v8::Global::new(scope, object),
19            }
20        })
21    }
22
23    /// Get the value using the given array index. Returns `Value::Undefined` if no element at the
24    /// index exists.
25    ///
26    /// Returns an error if `FromValue::from_value` fails for the element.
27    pub fn get<V: FromValue>(&self, index: u32) -> Result<V> {
28        self.mv8.try_catch(|scope| {
29            let array = v8::Local::new(scope, self.handle.clone());
30            let result = array.get_index(scope, index);
31            self.mv8.exception(scope)?;
32            Ok(Value::from_v8_value(&self.mv8, scope, result.unwrap()))
33        }).and_then(|v| v.into(&self.mv8))
34    }
35
36    /// Sets an array element using the given index and value.
37    ///
38    /// Returns an error if `ToValue::to_value` fails for the value.
39    pub fn set<V: ToValue>(&self, index: u32, value: V) -> Result<()> {
40        let value = value.to_value(&self.mv8)?;
41        self.mv8.try_catch(|scope| {
42            let array = v8::Local::new(scope, self.handle.clone());
43            let value = value.to_v8_value(scope);
44            array.set_index(scope, index, value);
45            self.mv8.exception(scope)
46        })
47    }
48
49    /// Returns the number of elements in the array.
50    pub fn len(&self) -> u32 {
51        self.mv8.scope(|scope| v8::Local::new(scope, self.handle.clone()).length())
52    }
53
54    /// Pushes an element to the end of the array. This is a shortcut for `set` using `len` as the
55    /// index.
56    pub fn push<V: ToValue>(&self, value: V) -> Result<()> {
57        self.set(self.len(), value)
58    }
59
60    /// Returns an iterator over the array's indexable values.
61    pub fn elements<V: FromValue>(self) -> Elements<V> {
62        Elements {
63            array: self,
64            index: 0,
65            len: None,
66            _phantom: PhantomData,
67        }
68    }
69}
70
71impl fmt::Debug for Array {
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        let len = self.len();
74        write!(f, "[")?;
75        for i in 0..len {
76            match self.get::<Value>(i) {
77                Ok(v) => write!(f, "{:?}", v)?,
78                Err(_) => write!(f, "?")?,
79            };
80            if i + 1 < len {
81                write!(f, ", ")?;
82            }
83        }
84        write!(f, "]")
85    }
86}
87
88pub struct Elements<V> {
89    array: Array,
90    index: u32,
91    len: Option<u32>,
92    _phantom: PhantomData<V>,
93}
94
95impl<V: FromValue> Iterator for Elements<V> {
96    type Item = Result<V>;
97
98    fn next(&mut self) -> Option<Self::Item> {
99        if self.len.is_none() {
100            self.len = Some(self.array.len());
101        }
102
103        if self.index >= self.len.unwrap() {
104            return None;
105        }
106
107        let result = self.array.get(self.index);
108        self.index += 1;
109        Some(result)
110    }
111}