1use super::*;
2
3
4#[allow(non_upper_case_globals)]
7pub const null: Object = Object::NULL;
8
9
10pub unsafe trait AsObject<'a>: Sized + Copy + Eq + Display + Into<FREObject> + Into<Object<'a>> {
28 const TYPE: Type;
29 fn as_object (self) -> Object<'a> {unsafe {transmute_unchecked(self)}}
30 fn as_ptr (self) -> FREObject {unsafe {transmute_unchecked(self)}}
31 fn is_null(self) -> bool {self.as_ptr().is_null()}
32 fn get_type(self) -> Type {
33 if self.is_null() {return Type::Null;}
34 let mut ty = FREObjectType(i32::default());
35 let r = unsafe {FREGetObjectType(self.as_ptr(), &mut ty)};
36 assert!(r.is_ok());
37 ty.into()
38 }
39 fn get_property (self, name: UCStr) -> Result<Object<'a>, ExternalError<'a>> {
40 let mut obj = std::ptr::null_mut();
41 let mut thrown = std::ptr::null_mut();
42 let r = unsafe {FREGetObjectProperty(self.as_ptr(), name.as_ptr(), &mut obj, &mut thrown)};
43 if let Ok(e) = ExternalError::try_from(r, Some(unsafe {transmute(thrown)})) {
44 Err(e)
45 }else{
46 Ok(unsafe {transmute(obj)})
47 }
48 }
49 fn set_property <O: AsObject<'a>> (self, name: UCStr, value: O) -> Result<(), ExternalError<'a>> {
50 let mut thrown = std::ptr::null_mut();
51 let r = unsafe {FRESetObjectProperty(self.as_ptr(), name.as_ptr(), value.as_ptr(), &mut thrown)};
52 if let Ok(e) = ExternalError::try_from(r, Some(unsafe {transmute(thrown)})) {
53 Err(e)
54 }else{
55 Ok(())
56 }
57 }
58 fn call_method (self, name: UCStr, args: Option<&[Object]>) -> Result<Object<'a>, ExternalError<'a>> {
59 let args = args.unwrap_or_default();
60 debug_assert!(args.len() <= u32::MAX as usize);
61 let mut obj = std::ptr::null_mut();
62 let mut thrown = std::ptr::null_mut();
63 let r = unsafe {FRECallObjectMethod(self.as_ptr(), name.as_ptr(), args.len() as u32, transmute(args.as_ptr()), &mut obj, &mut thrown)};
64 if let Ok(e) = ExternalError::try_from(r, Some(unsafe {transmute(thrown)})) {
65 Err(e)
66 }else{
67 Ok(unsafe {transmute(obj)})
68 }
69 }
70 #[allow(non_snake_case)]
72 fn toString (self) -> Result<StringObject<'a>, ExternalError<'a>> {
73 const NAME: UCStr = unsafe {UCStr::from_literal_unchecked(c"toString")};
74 self.call_method(NAME, None).map(|r|{unsafe {transmute(r)}})
75 }
76}
77impl<'a, O: AsObject<'a>> From<O> for UCStr {
78 fn from(value: O) -> Self {
79 value.to_string()
80 .replace('\0', "\\0")
81 .try_into()
82 .unwrap()
83 }
84}
85impl<'a, O: AsObject<'a>> From<&[O]> for UCStr {
86 fn from(value: &[O]) -> Self {
87 value.iter()
88 .map(|o|{o.to_string()})
89 .collect::<Vec<_>>()
90 .join(", ")
91 .replace('\0', "\\0")
92 .try_into()
93 .unwrap()
94 }
95}
96
97pub unsafe trait TryAs<'a, T>: AsObject<'a> + TryInto<T>
103where T: AsObject<'a> {
104 fn try_as (self) -> Result<T, Type> {
105 let ty = self.get_type();
106 if ty == T::TYPE {
107 Ok(unsafe {transmute_unchecked(self)})
108 }else{Err(ty)}
109 }
110}
111unsafe impl<'a, O> TryAs<'a, Object<'a>> for O
112where O: AsObject<'a> {
113 fn try_as (self) -> Result<Object<'a>, Type> {Ok(self.as_object())}
114}
115
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127#[repr(transparent)]
128pub struct Object <'a> (FREObject, PhantomData<&'a()>);
129impl<'a> Object<'a> {
130 pub const NULL: Object<'static> = Object(std::ptr::null_mut(), PhantomData);
131 #[allow(unused_variables)]
132 pub fn new (frt: &FlashRuntime<'a>, class: UCStr, args: Option<&[Object]>) -> Result<Object<'a>, ExternalError<'a>> {
133 let args = args.unwrap_or_default();
134 debug_assert!(args.len() <= u32::MAX as usize);
135 let mut obj = std::ptr::null_mut();
136 let mut thrown = std::ptr::null_mut();
137 let r = unsafe {FRENewObject(class.as_ptr(), args.len() as u32, transmute(args.as_ptr()), &mut obj, &mut thrown)};
138 if let Ok(e) = ExternalError::try_from(r, Some(unsafe {transmute(thrown)})) {
139 Err(e)
140 }else{
141 assert!(!obj.is_null());
142 Ok(unsafe {transmute(obj)})
143 }
144 }
145
146 pub fn with_native_window <F, R> (self, f: F) -> Result<R, FfiError>
154 where F: FnOnce (FRENativeWindow) -> R + Sync
155 {
156 let mut handle = std::ptr::null_mut();
157 let result = unsafe {FREAcquireNativeWindowHandle(self.as_ptr(), &mut handle)};
158 if let Ok(e) = FfiError::try_from(result) {return Err(e)};
159 let r = f(handle);
160 let result = unsafe {FREReleaseNativeWindowHandle(self.as_ptr())};
161 assert!(result.is_ok());
162 Ok(r)
163 }
164 pub fn with_native_window_3d <F, R> (self, f: F) -> Result<R, ExternalError<'a>>
170 where F: FnOnce (FRENativeWindow, &[Option<Context3D<'a>>]) -> R + Sync
171 {
172 const NAME_STAGE: UCStr = unsafe {UCStr::from_literal_unchecked(c"stage")};
173 const NAME_STAGE_3DS: UCStr = unsafe {UCStr::from_literal_unchecked(c"stage3Ds")};
174 const NAME_CONTEXT_3D: UCStr = unsafe {UCStr::from_literal_unchecked(c"context3D")};
175 let stage3ds: Vector = self.get_property(NAME_STAGE)?
176 .get_property(NAME_STAGE_3DS)?
177 .try_as()
178 .map_err(|_|ExternalError::C(FfiError::TypeMismatch))?;
179 let ctx3ds: Box<[Option<Context3D>]> = stage3ds.iter()
180 .map(|stage3d|{
181 stage3d.get_property(NAME_CONTEXT_3D)
182 .ok()
183 })
184 .map(|i|{
185 if let Some(ctx3d) = i {
186 if ctx3d.is_null() {None} else {Some(unsafe {transmute(ctx3d)})}
187 } else {None}
188 })
189 .collect();
190 let mut handle = std::ptr::null_mut();
191 let result = unsafe {FREAcquireNativeWindowHandle(self.as_ptr(), &mut handle)};
192 if let Ok(e) = FfiError::try_from(result) {return Err(e.into())};
193 let r = f(handle, ctx3ds.as_ref());
194 let result = unsafe {FREReleaseNativeWindowHandle(self.as_ptr())};
195 debug_assert!(result.is_ok());
196 Ok(r)
197 }
198}
199impl TryFrom<Object<'_>> for i32 {
200 type Error = FfiError;
201 fn try_from(value: Object) -> Result<Self, Self::Error> {
202 let mut val = i32::default();
203 let r = unsafe {FREGetObjectAsInt32(value.0, &mut val)};
204 if let Ok(e) = r.try_into() {return Err(e);}
205 Ok(val)
206 }
207}
208impl TryFrom<Object<'_>> for u32 {
209 type Error = FfiError;
210 fn try_from(value: Object) -> Result<Self, Self::Error> {
211 let mut val = u32::default();
212 let r = unsafe {FREGetObjectAsUint32(value.0, &mut val)};
213 if let Ok(e) = r.try_into() {return Err(e);}
214 Ok(val)
215 }
216}
217impl TryFrom<Object<'_>> for f64 {
218 type Error = FfiError;
219 fn try_from(value: Object) -> Result<Self, Self::Error> {
220 let mut val = f64::default();
221 let r = unsafe {FREGetObjectAsDouble(value.0, &mut val)};
222 if let Ok(e) = r.try_into() {return Err(e);}
223 Ok(val)
224 }
225}
226impl TryFrom<Object<'_>> for bool {
227 type Error = FfiError;
228 fn try_from(value: Object) -> Result<Self, Self::Error> {
229 let mut val = u32::default();
230 let r = unsafe {FREGetObjectAsBool(value.0, &mut val)};
231 if let Ok(e) = r.try_into() {return Err(e);}
232 Ok(val != 0)
233 }
234}
235impl TryFrom<Object<'_>> for String {
236 type Error = FfiError;
237 fn try_from(value: Object) -> Result<Self, Self::Error> {
238 let mut len = u32::default();
239 let mut ptr = std::ptr::null();
240 let r = unsafe {FREGetObjectAsUTF8(value.0, &mut len, &mut ptr)};
241 if let Ok(e) = r.try_into() {return Err(e);}
242 let bytes = unsafe {std::slice::from_raw_parts(ptr, len as usize)};
243 let s = unsafe {str::from_utf8_unchecked(bytes)};
244 Ok(s.to_owned())
245 }
246}
247impl<'a> TryFrom<Object<'a>> for Context<'a> {
257 type Error = FfiError;
258 fn try_from(value: Object) -> Result<Self, Self::Error> {
259 let mut ctx = std::ptr::null_mut();
260 let r = unsafe {FREGetFREContextFromExtensionContext(value.0, &mut ctx)};
261 if let Ok(e) = r.try_into() {
262 Err(e)
263 } else {Ok(unsafe {transmute(ctx)})}
264 }
265}
266impl Display for Object<'_> {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 if self.is_null() {return write!(f, "null");}
269 match self.toString() {
270 Ok(s) => {Display::fmt(s.value(), f)},
271 Err(e) => {
272 match e {
273 ExternalError::C(e) => Display::fmt(&e, f),
274 ExternalError::ActionScript(e) => {
275 if let Ok(s) = e.thrown().toString().map(|s|{s.value()}) {
276 write!(f, "{e} {s}")
277 } else {Display::fmt(&e, f)}
278 },
279 }
280 },
281 }
282 }
283}
284impl Default for Object<'_> {
285 fn default() -> Self {null}
286}
287unsafe impl<'a> AsObject<'a> for Object<'a> {const TYPE: Type = Type::Object;}
288impl From<()> for Object<'static> {fn from(_: ()) -> Self {null}}
289impl<'a, O: AsObject<'a>> From<Option<O>> for Object<'a> {
290 fn from(value: Option<O>) -> Self {
291 if let Some(obj) = value {
292 obj.as_object()
293 } else {null}
294 }
295}
296impl From<Object<'_>> for FREObject {fn from(value: Object) -> Self {value.as_ptr()}}