slinky/
document.rs

1/* SPDX-FileCopyrightText: © 2024 decompals */
2/* SPDX-License-Identifier: MIT */
3
4use std::{fs, path::Path};
5
6use serde::Deserialize;
7
8use crate::{
9    absent_nullable::AbsentNullable, assert_entry::AssertEntrySerial,
10    required_symbol::RequiredSymbolSerial, segment::SegmentSerial, settings::SettingsSerial,
11    symbol_assignment::SymbolAssignmentSerial, traits::Serial, vram_class::VramClassSerial,
12    AssertEntry, KeepSections, RequiredSymbol, Segment, Settings, SlinkyError, SymbolAssignment,
13    VramClass,
14};
15
16#[derive(PartialEq, Debug)]
17pub struct Document {
18    pub settings: Settings,
19
20    pub vram_classes: Vec<VramClass>,
21
22    pub segments: Vec<Segment>,
23
24    pub entry: Option<String>,
25    pub symbol_assignments: Vec<SymbolAssignment>,
26    pub required_symbols: Vec<RequiredSymbol>,
27    pub asserts: Vec<AssertEntry>,
28}
29
30impl Document {
31    pub fn read_file(path: &Path) -> Result<Self, SlinkyError> {
32        let f = match fs::File::open(path) {
33            Ok(f) => f,
34            Err(e) => {
35                return Err(SlinkyError::FailedFileOpen {
36                    path: path.to_path_buf(),
37                    description: e.to_string(),
38                })
39            }
40        };
41        let document_serial: DocumentSerial = match serde_yaml::from_reader(f) {
42            Ok(d) => d,
43            Err(e) => {
44                return Err(SlinkyError::FailedYamlParsing {
45                    description: e.to_string(),
46                })
47            }
48        };
49
50        document_serial.unserialize()
51    }
52}
53
54#[derive(Deserialize, PartialEq, Debug)]
55#[serde(deny_unknown_fields)]
56pub(crate) struct DocumentSerial {
57    #[serde(default)]
58    pub settings: AbsentNullable<SettingsSerial>,
59
60    #[serde(default)]
61    pub vram_classes: AbsentNullable<Vec<VramClassSerial>>,
62
63    pub segments: Vec<SegmentSerial>,
64
65    #[serde(default)]
66    pub entry: AbsentNullable<String>,
67    #[serde(default)]
68    pub symbol_assignments: AbsentNullable<Vec<SymbolAssignmentSerial>>,
69    #[serde(default)]
70    pub required_symbols: AbsentNullable<Vec<RequiredSymbolSerial>>,
71    #[serde(default)]
72    pub asserts: AbsentNullable<Vec<AssertEntrySerial>>,
73}
74
75impl DocumentSerial {
76    pub fn unserialize(self) -> Result<Document, SlinkyError> {
77        let settings = match self.settings.get_non_null_no_default("settings")? {
78            None => Settings::default(),
79            Some(v) => v.unserialize()?,
80        };
81
82        if self.segments.is_empty() {
83            return Err(SlinkyError::EmptyValue {
84                name: "segments".to_string(),
85            });
86        }
87
88        let vram_classes = self
89            .vram_classes
90            .get_non_null("vram_classes", Vec::new)?
91            .unserialize(&settings)?;
92
93        let mut segments = self.segments.unserialize(&settings)?;
94
95        let entry = self.entry.get_non_null_no_default("entry")?;
96
97        let symbol_assignments = self
98            .symbol_assignments
99            .get_non_null("symbol_assignments", Vec::new)?
100            .unserialize(&settings)?;
101
102        let required_symbols = self
103            .required_symbols
104            .get_non_null("required_symbols", Vec::new)?
105            .unserialize(&settings)?;
106
107        let asserts = self
108            .asserts
109            .get_non_null("asserts", Vec::new)?
110            .unserialize(&settings)?;
111
112        for segment in segments.iter_mut() {
113            if let Some(vram_class_name) = &segment.vram_class {
114                if let Some(vram_class) = vram_classes.iter().find(|x| x.name == *vram_class_name) {
115                    if vram_class.keep_sections != KeepSections::Absent {
116                        segment.pass_down_keep_sections(&vram_class.keep_sections);
117                    }
118                }
119            }
120        }
121
122        Ok(Document {
123            settings,
124            vram_classes,
125            segments,
126            entry,
127            symbol_assignments,
128            required_symbols,
129            asserts,
130        })
131    }
132}