Move Document info into new module
Getty Ritter
6 years ago
1 | use failure::Error; | |
2 | use image; | |
3 | use serde_json; | |
4 | use std::io::{Read, Write, Seek}; | |
5 | use zip::{ZipArchive, ZipWriter}; | |
6 | ||
7 | /// This value represents both the current document in-memory as well | |
8 | /// as the entirety of the values that we will want to both save and | |
9 | /// restore | |
10 | pub struct Document { | |
11 | pub tilesheet: image::DynamicImage, | |
12 | pub metadata: Metadata, | |
13 | pub rules: (), | |
14 | } | |
15 | ||
16 | /// This should be renamed; | |
17 | #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] | |
18 | pub struct Metadata { | |
19 | pub tile_width: u16, | |
20 | pub tile_height: u16, | |
21 | pub config_loop_forever: bool, | |
22 | } | |
23 | ||
24 | impl Document { | |
25 | pub fn open_from_file<R: Read + Seek>(r: &mut R) -> Result<Document, Error> { | |
26 | let mut archive = ZipArchive::new(r)?; | |
27 | let tilesheet = { | |
28 | let mut buf = Vec::new(); | |
29 | archive.by_name("tilesheet.png")?.read_to_end(&mut buf)?; | |
30 | image::load_from_memory(&buf)? | |
31 | }; | |
32 | let metadata = { | |
33 | let file = archive.by_name("metadata.json")?; | |
34 | serde_json::from_reader(file)? | |
35 | }; | |
36 | let rules = { | |
37 | let file = archive.by_name("rules.json")?; | |
38 | serde_json::from_reader(file)? | |
39 | }; | |
40 | Ok(Document{ tilesheet, metadata, rules }) | |
41 | } | |
42 | ||
43 | pub fn save_to_file<W: Write + Seek>(&self, w: &mut W) -> Result<(), Error> { | |
44 | use zip::write::FileOptions; | |
45 | ||
46 | let mut zip = ZipWriter::new(w); | |
47 | zip.start_file("tilesheet.png", FileOptions::default())?; | |
48 | self.tilesheet.write_to(&mut zip, image::ImageOutputFormat::PNG)?; | |
49 | ||
50 | zip.start_file("metadata.json", FileOptions::default())?; | |
51 | serde_json::to_writer(&mut zip, &self.metadata)?; | |
52 | ||
53 | zip.start_file("rules.json", FileOptions::default())?; | |
54 | serde_json::to_writer(&mut zip, &self.rules)?; | |
55 | ||
56 | zip.start_file("info.txt", FileOptions::default())?; | |
57 | writeln!( | |
58 | &mut zip, | |
59 | "Created by {} v{}", | |
60 | ::constants::PROGRAM_NAME, | |
61 | ::constants::PROGRAM_VERSION, | |
62 | )?; | |
63 | ||
64 | zip.finish()?; | |
65 | Ok(()) | |
66 | } | |
67 | ||
68 | pub fn dummy() -> Document { | |
69 | Document { | |
70 | tilesheet: image::DynamicImage::new_rgb8(32, 32), | |
71 | metadata: Metadata { | |
72 | tile_width: 16, | |
73 | tile_height: 16, | |
74 | config_loop_forever: false, | |
75 | }, | |
76 | rules: (), | |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | #[cfg(test)] | |
82 | mod tests { | |
83 | use super::Document; | |
84 | use std::io::{BufReader, Cursor}; | |
85 | ||
86 | #[test] | |
87 | fn round_trip() { | |
88 | let mut buf = Cursor::new(Vec::new()); | |
89 | let doc1 = Document::dummy(); | |
90 | doc1.save_to_file(&mut buf).unwrap(); | |
91 | let buf = buf.into_inner(); | |
92 | let doc2 = Document::open_from_file(&mut BufReader::new(Cursor::new(buf))).unwrap(); | |
93 | assert!(doc1.metadata == doc2.metadata); | |
94 | } | |
95 | } |
1 | pub mod document; | |
2 | pub use self::document::*; | |
3 | ||
4 | pub struct State { | |
5 | pub document: Document, | |
6 | pub save_state: SaveState, | |
7 | } | |
8 | ||
9 | #[derive(Debug)] | |
10 | pub enum SaveState { | |
11 | Unsaved, | |
12 | Modified, | |
13 | Saved, | |
14 | } |
1 | use failure::Error; | |
2 | use image; | |
3 | use serde_json; | |
4 | use std::io::{Read, Write, Seek}; | |
5 | use zip::{ZipArchive, ZipWriter}; | |
6 | ||
7 | pub struct State { | |
8 | pub document: Document, | |
9 | pub save_state: SaveState, | |
10 | } | |
11 | ||
12 | #[derive(Debug)] | |
13 | pub enum SaveState { | |
14 | Unsaved, | |
15 | Modified, | |
16 | Saved, | |
17 | } | |
18 | ||
19 | pub struct Document { | |
20 | pub tilesheet: image::DynamicImage, | |
21 | pub metadata: Metadata, | |
22 | pub rules: (), | |
23 | } | |
24 | ||
25 | #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] | |
26 | pub struct Metadata { | |
27 | pub tile_width: u16, | |
28 | pub tile_height: u16, | |
29 | pub config_loop_forever: bool, | |
30 | } | |
31 | ||
32 | impl Document { | |
33 | pub fn open_from_file<R: Read + Seek>(r: &mut R) -> Result<Document, Error> { | |
34 | let mut archive = ZipArchive::new(r)?; | |
35 | let tilesheet = { | |
36 | let mut buf = Vec::new(); | |
37 | archive.by_name("tilesheet.png")?.read_to_end(&mut buf)?; | |
38 | image::load_from_memory(&buf)? | |
39 | }; | |
40 | let metadata = { | |
41 | let file = archive.by_name("metadata.json")?; | |
42 | serde_json::from_reader(file)? | |
43 | }; | |
44 | let rules = { | |
45 | let file = archive.by_name("rules.json")?; | |
46 | serde_json::from_reader(file)? | |
47 | }; | |
48 | Ok(Document{ tilesheet, metadata, rules }) | |
49 | } | |
50 | ||
51 | pub fn save_to_file<W: Write + Seek>(&self, w: &mut W) -> Result<(), Error> { | |
52 | use zip::write::FileOptions; | |
53 | ||
54 | let mut zip = ZipWriter::new(w); | |
55 | zip.start_file("tilesheet.png", FileOptions::default())?; | |
56 | self.tilesheet.write_to(&mut zip, image::ImageOutputFormat::PNG)?; | |
57 | ||
58 | zip.start_file("metadata.json", FileOptions::default())?; | |
59 | serde_json::to_writer(&mut zip, &self.metadata)?; | |
60 | ||
61 | zip.start_file("rules.json", FileOptions::default())?; | |
62 | serde_json::to_writer(&mut zip, &self.rules)?; | |
63 | ||
64 | zip.start_file("info.txt", FileOptions::default())?; | |
65 | writeln!( | |
66 | &mut zip, | |
67 | "Created by {} v{}", | |
68 | ::constants::PROGRAM_NAME, | |
69 | ::constants::PROGRAM_VERSION, | |
70 | )?; | |
71 | ||
72 | zip.finish()?; | |
73 | Ok(()) | |
74 | } | |
75 | ||
76 | pub fn dummy() -> Document { | |
77 | Document { | |
78 | tilesheet: image::DynamicImage::new_rgb8(32, 32), | |
79 | metadata: Metadata { | |
80 | tile_width: 16, | |
81 | tile_height: 16, | |
82 | config_loop_forever: false, | |
83 | }, | |
84 | rules: (), | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
89 | #[cfg(test)] | |
90 | mod tests { | |
91 | use super::Document; | |
92 | use std::io::{BufReader, Cursor}; | |
93 | ||
94 | #[test] | |
95 | fn round_trip() { | |
96 | let mut buf = Cursor::new(Vec::new()); | |
97 | let doc1 = Document::dummy(); | |
98 | doc1.save_to_file(&mut buf).unwrap(); | |
99 | let buf = buf.into_inner(); | |
100 | let doc2 = Document::open_from_file(&mut BufReader::new(Cursor::new(buf))).unwrap(); | |
101 | assert!(doc1.metadata == doc2.metadata); | |
102 | } | |
103 | } |