#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Class {
pub name: String,
pub version: u64,
}
impl Class {
pub(crate) fn new(name: String, version: u64) -> Self {
Self { name, version }
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum OutputData {
String(String),
SignedInteger(i64),
UnsignedInteger(u64),
Float(f32),
Double(f64),
Byte(u8),
Array(Vec<u8>),
Class(Class),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Archivable {
Object(Class, Vec<OutputData>),
Data(Vec<OutputData>),
Class(Class),
Placeholder,
Type(Vec<Type>),
}
impl Archivable {
pub fn deserialize_as_nsstring(&self) -> Option<&str> {
if let Archivable::Object(Class { name, .. }, value) = self {
if name == "NSString" || name == "NSMutableString" {
if let Some(OutputData::String(text)) = value.first() {
return Some(text);
}
}
}
None
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Type {
Utf8String,
EmbeddedData,
Object,
SignedInt,
UnsignedInt,
Float,
Double,
String(String),
Array(usize),
Unknown(u8),
}
impl Type {
pub(crate) fn from_byte(byte: &u8) -> Self {
match byte {
0x40 => Self::Object,
0x2B => Self::Utf8String,
0x2A => Self::EmbeddedData,
0x66 => Self::Float,
0x64 => Self::Double,
0x63 | 0x69 | 0x6c | 0x71 | 0x73 => Self::SignedInt,
0x43 | 0x49 | 0x4c | 0x51 | 0x53 => Self::UnsignedInt,
other => Self::Unknown(*other),
}
}
pub(crate) fn new_string(string: String) -> Self {
Self::String(string)
}
pub(crate) fn get_array_length(types: &[u8]) -> Option<Vec<Type>> {
if types.first() == Some(&0x5b) {
let len =
types[1..]
.iter()
.take_while(|a| a.is_ascii_digit())
.fold(None, |acc, ch| {
char::from_u32(*ch as u32)?
.to_digit(10)
.map(|b| acc.unwrap_or(0) * 10 + b)
})?;
return Some(vec![Type::Array(len as usize)]);
}
None
}
}
#[derive(Debug)]
pub(crate) enum ClassResult {
Index(usize),
ClassHierarchy(Vec<Archivable>),
}