1use crate::avm1::opcode::OpCode;
2use crate::tag_code::TagCode;
3use std::{borrow, error, fmt, io};
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug)]
9pub enum Error {
10 Avm1ParseError {
13 opcode: u8,
14 source: Option<Box<dyn error::Error + Send + Sync + 'static>>,
15 },
16
17 InvalidData(borrow::Cow<'static, str>),
19
20 SwfParseError {
23 tag_code: u16,
24 source: Box<dyn error::Error + Send + Sync + 'static>,
25 },
26
27 IoError(io::Error),
29
30 Unsupported(borrow::Cow<'static, str>),
32}
33
34impl Error {
35 #[inline]
37 pub fn avm1_parse_error(opcode: u8) -> Self {
38 Self::Avm1ParseError {
39 opcode,
40 source: None,
41 }
42 }
43
44 #[inline]
46 pub fn avm1_parse_error_with_source(
47 opcode: u8,
48 source: impl error::Error + Send + Sync + 'static,
49 ) -> Self {
50 Self::Avm1ParseError {
51 opcode,
52 source: Some(Box::new(source)),
53 }
54 }
55
56 #[inline]
58 pub fn invalid_data(message: impl Into<borrow::Cow<'static, str>>) -> Self {
59 Self::InvalidData(message.into())
60 }
61
62 #[inline]
64 pub fn swf_parse_error(
65 tag_code: u16,
66 source: impl error::Error + Send + Sync + 'static,
67 ) -> Self {
68 Self::SwfParseError {
69 tag_code,
70 source: Box::new(source),
71 }
72 }
73
74 #[inline]
76 pub fn unsupported(message: impl Into<borrow::Cow<'static, str>>) -> Self {
77 Self::Unsupported(message.into())
78 }
79}
80
81impl fmt::Display for Error {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 match self {
84 Self::Avm1ParseError { opcode, source } => {
85 write!(f, "Error parsing AVM1 action {}", OpCode::format(*opcode))?;
86 if let Some(source) = source {
87 write!(f, ": {source}")?;
88 }
89 Ok(())
90 }
91 Self::SwfParseError { tag_code, source } => {
92 write!(
93 f,
94 "Error parsing SWF tag {}: {}",
95 TagCode::format(*tag_code),
96 source
97 )
98 }
99 Self::IoError(e) => e.fmt(f),
100 Self::InvalidData(message) => write!(f, "Invalid data: {message}"),
101 Self::Unsupported(message) => write!(f, "Unsupported data: {message}"),
102 }
103 }
104}
105
106impl error::Error for Error {
107 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
108 match self {
109 Self::Avm1ParseError { source, .. } => match source {
110 Some(s) => Some(s.as_ref()),
111 None => None,
112 },
113 Self::IoError(e) => e.source(),
114 Self::InvalidData(_) => None,
115 Self::SwfParseError { source, .. } => Some(source.as_ref()),
116 Self::Unsupported(_) => None,
117 }
118 }
119}
120
121impl From<io::Error> for Error {
122 fn from(error: io::Error) -> Self {
123 Self::IoError(error)
124 }
125}
126
127#[cfg(test)]
128#[test]
129fn test_error_send_sync() {
130 fn assert_send_sync<T: Send + Sync>() {}
131 assert_send_sync::<Error>()
132}