1use std::any::TypeId;
6use std::rc::Rc;
7
8use crate::animation::{KeyedObject, KeyedProperty, LinearAnimation};
9use crate::artboard::Artboard;
10use crate::backboard::Backboard;
11use crate::component::Component;
12use crate::core::{self, BinaryReader, Core, Object};
13use crate::importers::{
14 ArtboardImporter, ImportStack, ImportStackObject, KeyedObjectImporter, KeyedPropertyImporter,
15 LinearAnimationImporter,
16};
17use crate::runtime_header::RuntimeHeader;
18use crate::status_code::StatusCode;
19
20const MAJOR_VERSION: u32 = 7;
22const _MINOR_VERSION: u32 = 0;
24
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub enum ImportError {
27 UnsupportedVersion,
29 Malformed,
31}
32
33fn read_runtime_object(
34 reader: &mut BinaryReader<'_>,
35 header: &RuntimeHeader,
36 objects: &mut Vec<Rc<dyn Core>>,
37) -> Option<(Object, TypeId)> {
38 let id = core::get_type_id(reader.read_var_u64()? as u16)?;
39 let (core, object) = <dyn Core>::from_type_id(id)?;
40 objects.push(Rc::clone(&core));
41
42 loop {
43 let property_key = reader.read_var_u64()? as u16;
44 if property_key == 0 {
45 break;
46 }
47
48 if !core.write(property_key, reader) {
49 match header.property_file_id(property_key as u32)? {
52 0 => {
53 reader.read_var_u64()?;
54 }
55 1 => {
56 reader.read_string()?;
57 }
58 2 => {
59 reader.read_f32()?;
60 }
61 3 => {
62 reader.read_u32()?;
63 }
64 _ => return None,
65 }
66 }
67 }
68
69 Some((object, id))
70}
71
72#[derive(Debug)]
73pub struct File {
74 backboard: Object<Backboard>,
75 artboards: Vec<Object<Artboard>>,
76 #[allow(unused)]
78 objects: Vec<Rc<dyn Core>>,
79}
80
81impl File {
82 pub fn import(reader: &mut BinaryReader<'_>) -> Result<Self, ImportError> {
83 let header = RuntimeHeader::read(reader).ok_or(ImportError::Malformed)?;
84
85 if header.major_version() != MAJOR_VERSION {
86 return Err(ImportError::UnsupportedVersion);
87 }
88
89 Self::read(reader, &header).ok_or(ImportError::Malformed)
90 }
91
92 fn read(reader: &mut BinaryReader<'_>, header: &RuntimeHeader) -> Option<Self> {
93 let mut objects = Vec::new();
94 let mut import_stack = ImportStack::default();
95 let mut backboard_option = None;
96 let mut artboards = Vec::new();
97
98 while !reader.reached_end() {
99 let (object, id) = read_runtime_object(reader, header, &mut objects)?;
100
101 let stack_object: Option<Box<dyn ImportStackObject>> =
102 if let Some(artboard) = object.try_cast::<Artboard>() {
103 Some(Box::new(ArtboardImporter::new(artboard)))
104 } else if let Some(animation) = object.try_cast::<LinearAnimation>() {
105 Some(Box::new(LinearAnimationImporter::new(animation)))
106 } else if let Some(keyed_object) = object.try_cast::<KeyedObject>() {
107 Some(Box::new(KeyedObjectImporter::new(keyed_object)))
108 } else if let Some(keyed_property) = object.try_cast::<KeyedProperty>() {
109 let importer = import_stack
110 .latest::<LinearAnimationImporter>(TypeId::of::<LinearAnimation>())?;
111 Some(Box::new(KeyedPropertyImporter::new(importer.animation(), keyed_property)))
112 } else {
113 None
114 };
115
116 if import_stack.make_latest(id, stack_object) != StatusCode::Ok {
117 return None;
118 }
119
120 if object.as_ref().import(object.clone(), &import_stack) == StatusCode::Ok {
121 if let Some(backboard) = object.try_cast::<Backboard>() {
122 backboard_option = Some(backboard);
123 }
124
125 if let Some(artboard) = object.try_cast::<Artboard>() {
126 artboards.push(artboard);
127 }
128 }
129 }
130
131 if import_stack.resolve() != StatusCode::Ok {
132 return None;
133 }
134
135 Some(Self { backboard: backboard_option?, artboards, objects })
136 }
137
138 pub fn backboard(&self) -> Object<Backboard> {
139 self.backboard.clone()
140 }
141
142 pub fn artboard(&self) -> Option<Object<Artboard>> {
143 self.artboards.get(0).cloned()
144 }
145
146 pub fn get_artboard(&self, name: &str) -> Option<Object<Artboard>> {
147 self.artboards
148 .iter()
149 .find(|artboard| artboard.cast::<Component>().as_ref().name() == name)
150 .cloned()
151 }
152
153 pub fn artboards(&self) -> impl Iterator<Item = &Object<Artboard>> {
154 self.artboards.iter()
155 }
156}