Skip to main content

fre_rs/
error.rs

1use super::*;
2
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum ExternalError<'a> {
6    C(FfiError),
7    ActionScript(ActionScriptError<'a>),
8}
9impl<'a> ExternalError<'a> {
10    /// Attempts to convert a [`FREResult`] into [`ExternalError`].
11    ///
12    /// If the result represents an ActionScript error and `thrown` is [`Some`],
13    /// the provided object is used as the error value.
14    ///
15    /// If `thrown` is [`None`], the thrown object is ignored or assumed unavailable.
16    ///
17    /// # Notes
18    /// When an ActionScript throw occurs, the provided object is assumed to be a valid [`FREObject`].
19    /// However, ActionScript may throw [`null`].
20    pub fn try_from (result: FREResult, thrown: Option<as3::Object<'a>>) -> Result<Self, ()> {
21        let r = result.try_into();
22        if let (Ok(Self::ActionScript(_)), Some(obj)) = (r, thrown) {
23            return Ok(ActionScriptError(obj).into());
24        }
25        r
26    }
27}
28impl From<FfiError> for ExternalError<'static> {
29    fn from(value: FfiError) -> Self {Self::C(value)}
30}
31impl<'a> From<ActionScriptError<'a>> for ExternalError<'a> {
32    fn from(value: ActionScriptError<'a>) -> Self {Self::ActionScript(value)}
33}
34impl TryFrom<FREResult> for ExternalError<'static> {
35    type Error = ();
36    fn try_from(value: FREResult) -> Result<Self, ()> {
37        FfiError::try_from(value).map(|e|{
38            if let FfiError::UnexpectedResult(v)=e && v==FREResult::FRE_ACTIONSCRIPT_ERROR {
39                ActionScriptError::IGNORED.into()
40            }else{e.into()}
41        })
42    }
43}
44impl Display for ExternalError<'_> {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Self::C(e) => Display::fmt(e, f),
48            Self::ActionScript(e) => Display::fmt(e, f),
49        }
50    }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum FfiError {
55    NoSuchName,
56    InvalidObject,
57    TypeMismatch,
58    InvalidArgument,
59    ReadOnly,
60    WrongThread,
61    IllegalState,
62    InsufficientMemory,
63    UnexpectedResult(FREResult),
64}
65impl Display for FfiError {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        const PREFIX: &str = "[FfiError]";
68        match *self {
69            FfiError::NoSuchName => write!(f, "{PREFIX} The name of a class, property, or method passed as a parameter does not match an ActionScript class name, property, or method."),
70            FfiError::InvalidObject => write!(f, "{PREFIX} An FREObject parameter is invalid. For examples of invalid FREObject variables, see 'FREObject validity'. https://help.adobe.com/en_US/air/extensions/WS460ee381960520ad-866f9c112aa6e1ad46-7ff9.html"),
71            FfiError::TypeMismatch => write!(f, "{PREFIX} An FREObject parameter does not represent an object of the ActionScript class expected by the called function."),
72            FfiError::InvalidArgument => write!(f, "{PREFIX} A pointer parameter is `NULL`."),
73            FfiError::ReadOnly => write!(f, "{PREFIX} The function attempted to modify a read-only property of an ActionScript object."),
74            FfiError::WrongThread => write!(f, "{PREFIX} The method was called from a thread other than the one on which the runtime has an outstanding call to a native extension function."),
75            FfiError::IllegalState => write!(f, "{PREFIX} A call was made to a native extensions C API function when the extension context was in an illegal state for that call. This return value occurs in the following situation. The context has acquired access to an ActionScript BitmapData or ByteArray class object. With one exception, the context can call no other C API functions until it releases the BitmapData or ByteArray object. The one exception is that the context can call `FREInvalidateBitmapDataRect()` after calling `FREAcquireBitmapData()` or `FREAcquireBitmapData2()`."),
76            FfiError::InsufficientMemory => write!(f, "{PREFIX} The runtime could not allocate enough memory to change the size of an Array or Vector object."),
77            FfiError::UnexpectedResult(code) => write!(f, "{PREFIX} Unexpected FREResult. ({code:#08X})"),
78        }
79    }
80}
81impl Error for FfiError {}
82impl TryFrom<FREResult> for FfiError {
83    type Error = ();
84    /// Converts a [`FREResult`] into [`FfiError`].
85    ///
86    /// Assumes `value` is **not** [`FREResult::FRE_ACTIONSCRIPT_ERROR`].
87    /// If it is, it will be treated as an unexpected result.
88    fn try_from(value: FREResult) -> Result<Self, ()> {
89        Ok(match value {
90            FREResult::FRE_OK => return Err(()),
91            FREResult::FRE_INVALID_OBJECT => Self::InvalidObject,
92            FREResult::FRE_TYPE_MISMATCH => Self::TypeMismatch,
93            FREResult::FRE_INVALID_ARGUMENT => Self::InvalidArgument,
94            FREResult::FRE_READ_ONLY => Self::ReadOnly,
95            FREResult::FRE_WRONG_THREAD => Self::WrongThread,
96            FREResult::FRE_ILLEGAL_STATE => Self::IllegalState,
97            FREResult::FRE_INSUFFICIENT_MEMORY => Self::InsufficientMemory,
98            _ => Self::UnexpectedResult(value),
99        })
100    }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104#[repr(transparent)]
105pub struct ActionScriptError<'a> (as3::Object<'a>);
106impl<'a> ActionScriptError<'a> {
107    const IGNORED: ActionScriptError<'static> = ActionScriptError(as3::null);
108    /// May be null if the caller does not want to receive this handle.
109    pub fn thrown (self) -> as3::Object<'a> {self.0}
110}
111impl Display for ActionScriptError<'_> {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        write!(f, "[ActionScriptError] An ActionScript error occurred, and an exception was thrown. The C API functions that can result in this error allow you to specify an FREObject to receive information about the exception.")
114    }
115}
116impl Error for ActionScriptError<'_> {}
117
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub enum ContextError {
121    InvalidContext,
122    NullRegistry,
123    InvalidRegistry,
124    MethodsNotRegistered,
125    MethodNotFound,
126    FfiCallFailed(FfiError),
127    BorrowRegistryConflict,
128}
129impl Display for ContextError {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        write!(f, "[ContextError] {self:?}")
132    }
133}
134impl Error for ContextError {}
135impl From<FfiError> for ContextError {
136    fn from(value: FfiError) -> Self {Self::FfiCallFailed(value)}
137}