Skip to main content

fre_rs/types/
misc.rs

1use super::*;
2
3
4crate::class! {@Typeof
5    /// A reference to the AS3 object `Array`.
6    /// 
7    /// Some methods are not yet implemented.
8    /// 
9    Array
10}
11impl<'a> Array<'a> {
12    pub fn get_length (self) -> u32 {
13        let mut value = MaybeUninit::<u32>::uninit();
14        let r = unsafe {FREGetArrayLength(self.as_ptr(), value.as_mut_ptr())};
15        debug_assert!(r.is_ok());
16        unsafe {value.assume_init()}
17    }
18    /// [`Err`]=> [FfiError::InsufficientMemory];
19    /// 
20    pub fn set_length (self, value: u32) -> Result<(), FfiError> {
21        let r = unsafe {FRESetArrayLength(self.as_ptr(), value)};
22        if let Ok(e) = FfiError::try_from(r) {
23            Err(e)
24        } else {Ok(())}
25    }
26    pub fn get (self, index: u32) -> Object<'a> {
27        let mut object = MaybeUninit::<FREObject>::uninit();
28        let r = unsafe {FREGetArrayElementAt(self.as_ptr(), index, object.as_mut_ptr())};
29        debug_assert!(r.is_ok());
30        unsafe {transmute(object)}
31    }
32    pub fn set <O: AsObject<'a>> (self, index: u32, value: O) {
33        let r = unsafe {FRESetArrayElementAt(self.as_ptr(), index, value.as_ptr())};
34        debug_assert!(r.is_ok());
35    }
36    pub fn new (ctx: &CurrentContext<'a>, num_elements: Option<NonNegativeInt>) -> Self {
37        let mut arg = as3::null;
38        let num_elements = num_elements.map(|v|{
39            arg = int::new(ctx, v.get()).as_object();
40            std::slice::from_ref(&arg)
41        });
42        unsafe {ctx.construct(crate::ucstringify!(Array), num_elements)
43            .unwrap()
44            .as_unchecked()}
45    }
46    pub fn from_slice (ctx: &CurrentContext<'a>, elements: &[Object<'a>]) -> Self {
47        debug_assert!(elements.len() <= i32::MAX as usize);
48        if elements.len() == 1 && elements[0].get_type() == Type::Number {
49            let arr = Self::new(ctx, NonNegativeInt::new(1));
50            arr.set(0, *unsafe {elements.get_unchecked(0)});
51            arr
52        } else {
53            unsafe {ctx.construct(crate::ucstringify!(Array), Some(elements))
54                .unwrap()
55                .as_unchecked()}
56        }
57    }
58    pub fn extend_from_slice (self, elements: &[Object]) -> u32 {
59        self.call_method(crate::ucstringify!(push), Some(elements))
60            .unwrap()
61            .try_into()
62            .unwrap()
63    }
64    pub fn push <O: AsObject<'a>> (self, element: O) -> u32 {
65        let element = element.as_object();
66        let elements = std::slice::from_ref(&element);
67        self.extend_from_slice(elements)
68    }
69    pub fn iter(self) -> ArrayIter<'a> {ArrayIter::new(self)}
70}
71impl<'a> IntoIterator for Array<'a> {
72    type Item = Object<'a>;
73    type IntoIter = ArrayIter<'a>;
74    fn into_iter(self) -> Self::IntoIter {self.iter()}
75}
76
77
78crate::class! {@Typeof
79    /// A reference to the AS3 object `Vector.<*>`.
80    /// 
81    /// Some properties and methods are not yet implemented.
82    /// 
83    Vector
84}
85impl<'a> Vector<'a> {
86    pub fn get_length (self) -> u32 {
87        let mut value = MaybeUninit::<u32>::uninit();
88        let r = unsafe {FREGetArrayLength(self.as_ptr(), value.as_mut_ptr())};
89        debug_assert!(r.is_ok());
90        unsafe {value.assume_init()}
91    }
92
93    /// [`Err`]=> [FfiError::InsufficientMemory], [FfiError::ReadOnly];
94    /// 
95    pub fn set_length (self, value: u32) -> Result<(), FfiError> {
96        let r = unsafe {FRESetArrayLength(self.as_ptr(), value)};
97        if let Ok(e) = FfiError::try_from(r) {
98            Err(e)
99        } else {Ok(())}
100    }
101
102    /// [`Err`]=> [FfiError::InvalidArgument];
103    /// 
104    pub fn get (self, index: u32) -> Result<Object<'a>, FfiError> {
105        let mut object = MaybeUninit::<FREObject>::uninit();
106        let r = unsafe {FREGetArrayElementAt(self.as_ptr(), index, object.as_mut_ptr())};
107        if let Ok(e) = FfiError::try_from(r) {
108            Err(e)
109        } else {
110            Ok(unsafe {transmute(object)})
111        }
112    }
113
114    /// [`Err`]=> [FfiError::TypeMismatch];
115    /// 
116    pub fn set <O: AsObject<'a>> (self, index: u32, value: O) -> Result<(), FfiError> {
117        let r = unsafe {FRESetArrayElementAt(self.as_ptr(), index, value.as_ptr())};
118        if let Ok(e) = FfiError::try_from(r) {
119            Err(e)
120        } else {Ok(())}
121    }
122    pub fn iter(self) -> VectorIter<'a> {VectorIter::new(self)}
123}
124impl<'a> IntoIterator for Vector<'a> {
125    type Item = Object<'a>;
126    type IntoIter = VectorIter<'a>;
127    fn into_iter(self) -> Self::IntoIter {self.iter()}
128}
129
130
131crate::class! {@Typeof
132    /// A reference to the AS3 object `flash.utils.ByteArray`.
133    /// 
134    /// Some properties and methods are not yet implemented.
135    /// 
136    ByteArray
137}
138impl<'a> ByteArray<'a> {
139    pub fn new (_: &CurrentContext<'a>, length: u32) -> Self {
140        let descriptor = FREByteArray {length, bytes: std::ptr::null_mut()};
141        let mut object = MaybeUninit::<FREObject>::uninit();
142        let r = unsafe {FRENewByteArray(transmute(&descriptor), object.as_mut_ptr())};
143        debug_assert!(r.is_ok());
144        let object = unsafe {object.assume_init()};
145        assert!(!object.is_null());
146        unsafe {transmute(object)}
147    }
148    pub fn from_bytes (_: &CurrentContext<'a>, bytes: impl AsRef<[u8]>) -> Self {
149        let bytes = bytes.as_ref();
150        debug_assert!(bytes.len() <= u32::MAX as usize);
151        let descriptor = FREByteArray {length: bytes.len() as u32, bytes: bytes.as_ptr() as FREBytes};
152        let mut object = MaybeUninit::<FREObject>::uninit();
153        let r = unsafe {FRENewByteArray(transmute(&descriptor), object.as_mut_ptr())};
154        debug_assert!(r.is_ok());
155        let object = unsafe {object.assume_init()};
156        assert!(!object.is_null());
157        unsafe {transmute(object)}
158    }
159
160    /// During the closure call stack, the Flash runtime is in a restricted state
161    /// where most APIs are unavailable, and [`Sync`] is used to prevent illegal
162    /// FFI call ordering.
163    /// 
164    pub fn with <F, R> (self, f: F) -> R
165    where F: Sync + FnOnce (&mut [u8]) -> R
166    {
167        let mut descriptor = MaybeUninit::<FREByteArray>::uninit();
168        let result = unsafe {FREAcquireByteArray(self.as_ptr(), descriptor.as_mut_ptr())};
169        assert!(result.is_ok());
170        let descriptor = unsafe {descriptor.assume_init()};
171        assert!(!descriptor.bytes.is_null());
172        let bytes = unsafe {std::slice::from_raw_parts_mut(descriptor.bytes, descriptor.length as usize)};
173        let r = f(bytes);
174        let result = unsafe {FREReleaseByteArray(self.as_ptr())};
175        debug_assert!(result.is_ok());
176        r
177    }
178}
179
180
181crate::class! {
182    /// A reference to the AS3 object `Error`.
183    /// 
184    Error
185}
186impl<'a> Error<'a> {
187    #[allow(non_snake_case)]
188    pub fn get_errorID(self) -> i32 {
189        let value = self.get_property(crate::ucstringify!(errorID)).unwrap().try_into().unwrap();
190        value
191    }
192
193    pub fn get_message(self) -> Option<as3::String<'a>> {
194        let value = self.get_property(crate::ucstringify!(message)).unwrap().try_as().ok();
195        value
196    }
197    pub fn set_message(self, value: Option<as3::String>) {
198        let r = self.set_property(crate::ucstringify!(message), Object::from(value));
199        debug_assert!(r.is_ok());
200    }
201
202    pub fn get_name(self) -> Option<as3::String<'a>> {
203        let value = self.get_property(crate::ucstringify!(name)).unwrap().try_as().ok();
204        value
205    }
206    pub fn set_name(self, value: Option<as3::String>) {
207        let r = self.set_property(crate::ucstringify!(name), Object::from(value));
208        debug_assert!(r.is_ok());
209    }
210    
211    pub fn new(ctx: &CurrentContext<'a>, message: Option<&str>, id: i32) -> Self {
212        let message = message.map(|s|as3::String::new(ctx, s));
213        let id = int::new(ctx, id);
214        let args = vec![message.into(), id.as_object()].into_boxed_slice();
215        let object= ctx.construct(crate::ucstringify!(Error), Some(args.as_ref())).unwrap();
216        unsafe {object.as_unchecked()}
217    }
218}
219