Skip to main content

imessage_database/error/
plist.rs

1/*!
2 Errors that can happen when parsing plist data.
3*/
4
5use crabstep::error::TypedStreamError;
6
7use crate::error::digital_touch::DigitalTouchError;
8use crate::error::handwriting::HandwritingError;
9use crate::error::streamtyped::StreamTypedError;
10use std::fmt::{Display, Formatter, Result};
11
12/// Errors that can happen when parsing the plist data stored in the `payload_data` field
13#[derive(Debug)]
14pub enum PlistParseError {
15    /// Expected key was not found in the plist data
16    MissingKey(String),
17    /// No value was found at the specified index
18    NoValueAtIndex(usize),
19    /// Value had an incorrect type for the specified key
20    InvalidType(String, String),
21    /// Value had an incorrect type at the specified index
22    InvalidTypeIndex(usize, String),
23    /// Dictionary has mismatched number of keys and values
24    InvalidDictionarySize(usize, usize),
25    /// UID value cannot be represented as an object-table index on this target.
26    UidOutOfRange(u64),
27    /// No payload data was found
28    NoPayload,
29    /// Message is not of the expected type
30    WrongMessageType,
31    /// Could not parse an edited message
32    InvalidEditedMessage(String),
33    /// Error from stream typed parsing
34    StreamTypedError(StreamTypedError),
35    /// Error from typedstream parsing
36    TypedStreamError(TypedStreamError),
37    /// Error from handwriting data parsing
38    HandwritingError(HandwritingError),
39    /// Error from Digital Touch data parsing
40    DigitalTouchError(DigitalTouchError),
41    /// Error parsing a poll message
42    PollError,
43    /// Exceeded the maximum UID-reference resolution depth (likely a reference cycle)
44    RecursionLimit,
45}
46
47impl Display for PlistParseError {
48    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
49        match self {
50            PlistParseError::MissingKey(key) => write!(fmt, "Expected key {key}, found nothing!"),
51            PlistParseError::NoValueAtIndex(idx) => {
52                write!(fmt, "Payload referenced index {idx}, but there is no data!")
53            }
54            PlistParseError::InvalidType(key, value) => {
55                write!(fmt, "Invalid data found at {key}, expected {value}")
56            }
57            PlistParseError::InvalidTypeIndex(idx, value) => {
58                write!(
59                    fmt,
60                    "Invalid data found at object index {idx}, expected {value}"
61                )
62            }
63            PlistParseError::InvalidDictionarySize(a, b) => write!(
64                fmt,
65                "Invalid dictionary size, found {a} keys and {b} values"
66            ),
67            PlistParseError::UidOutOfRange(uid) => {
68                write!(fmt, "UID value {uid} cannot be used as an object index")
69            }
70            PlistParseError::NoPayload => write!(fmt, "Unable to acquire payload data!"),
71            PlistParseError::WrongMessageType => write!(fmt, "Message is not an app message!"),
72            PlistParseError::InvalidEditedMessage(message) => {
73                write!(fmt, "Unable to parse message from binary data: {message}")
74            }
75            PlistParseError::StreamTypedError(why) => write!(fmt, "{why}"),
76            PlistParseError::HandwritingError(why) => write!(fmt, "{why}"),
77            PlistParseError::DigitalTouchError(why) => write!(fmt, "{why}"),
78            PlistParseError::TypedStreamError(typed_stream_error) => {
79                write!(fmt, "TypedStream error: {typed_stream_error}")
80            }
81            PlistParseError::PollError => write!(fmt, "Unable to parse Poll Message!"),
82            PlistParseError::RecursionLimit => write!(
83                fmt,
84                "Exceeded maximum depth while resolving UID references; the archive may contain a reference cycle"
85            ),
86        }
87    }
88}
89
90impl std::error::Error for PlistParseError {
91    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
92        match self {
93            PlistParseError::StreamTypedError(e) => Some(e),
94            PlistParseError::TypedStreamError(e) => Some(e),
95            PlistParseError::HandwritingError(e) => Some(e),
96            PlistParseError::DigitalTouchError(e) => Some(e),
97            _ => None,
98        }
99    }
100}
101
102impl From<TypedStreamError> for PlistParseError {
103    fn from(error: TypedStreamError) -> Self {
104        PlistParseError::TypedStreamError(error)
105    }
106}
107
108impl From<StreamTypedError> for PlistParseError {
109    fn from(error: StreamTypedError) -> Self {
110        PlistParseError::StreamTypedError(error)
111    }
112}