Skip to content

Commit

Permalink
Start parsing vram classing, do nothing about them yet
Browse files Browse the repository at this point in the history
  • Loading branch information
AngheloAlf committed Apr 27, 2024
1 parent a8f2912 commit a0ab1b9
Show file tree
Hide file tree
Showing 7 changed files with 1,107 additions and 10 deletions.
20 changes: 17 additions & 3 deletions slinky/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ use std::{fs, path::Path};
use serde::Deserialize;

use crate::{
absent_nullable::AbsentNullable, segment::SegmentSerial, settings::SettingsSerial, Segment,
Settings, SlinkyError,
absent_nullable::AbsentNullable, segment::SegmentSerial, settings::SettingsSerial, vram_class::VramClassSerial, Segment, Settings, SlinkyError, VramClass
};

#[derive(PartialEq, Debug)]
pub struct Document {
pub settings: Settings,

pub vram_classes: Vec<VramClass>,

pub segments: Vec<Segment>,
}

Expand Down Expand Up @@ -47,6 +48,9 @@ pub(crate) struct DocumentSerial {
#[serde(default)]
pub settings: AbsentNullable<SettingsSerial>,

#[serde(default)]
pub vram_classes: AbsentNullable<Vec<VramClassSerial>>,

pub segments: Vec<SegmentSerial>,
}

Expand All @@ -63,11 +67,21 @@ impl DocumentSerial {
});
}

let mut vram_classes = Vec::new();
match self.vram_classes.get_non_null_no_default("vram_classes")? {
None => (),
Some(v) => {
for c in v {
vram_classes.push(c.unserialize(&settings)?);
}
},
}

let mut segments = Vec::with_capacity(self.segments.len());
for seg in self.segments {
segments.push(seg.unserialize(&settings)?);
}

Ok(Document { settings, segments })
Ok(Document { settings, vram_classes, segments })
}
}
3 changes: 3 additions & 0 deletions slinky/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ pub enum SlinkyError {

#[error("Field '{required}' is required if field '{other}' is given")]
MissingRequiredFieldCombo { required: String, other: String },

#[error("At least one of the following options should be provided: {fields}")]
MissingAnyOfOptionalFields { fields: String },
}
5 changes: 5 additions & 0 deletions slinky/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ mod file_info;
mod file_kind;
mod segment;

mod vram_class;

mod document;

mod linker_writer;
Expand All @@ -26,6 +28,9 @@ pub use file_info::FileInfo;
pub use file_kind::FileKind;
pub use segment::Segment;


pub use vram_class::VramClass;

pub use document::Document;

pub use linker_writer::LinkerWriter;
Expand Down
40 changes: 33 additions & 7 deletions slinky/src/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ pub struct Segment {
pub files: Vec<FileInfo>,

/// If not None then forces the segment to have a fixed vram address instead of following the previous segment.
/// Not compatible with `follows_segment`.
/// Not compatible with `follows_segment` or `vram_class`.
pub fixed_vram: Option<u32>,

/// If not None then forces the segment's vram address to be after the specified segment instead of following the previous one.
/// Not compatible with `fixed_vram`.
/// Not compatible with `fixed_vram` or `vram_class`.
pub follows_segment: Option<String>,

/// Not compatible with `fixed_vram` or `follows_segment`.
pub vram_class: Option<String>,

// The default value of the following members come from Settings
pub alloc_sections: Vec<String>,
pub noload_sections: Vec<String>,
Expand All @@ -48,6 +51,8 @@ pub(crate) struct SegmentSerial {

pub follows_segment: AbsentNullable<String>,

pub vram_class: AbsentNullable<String>,

// The default of the following come from Options
#[serde(default)]
pub alloc_sections: AbsentNullable<Vec<String>>,
Expand Down Expand Up @@ -96,11 +101,31 @@ impl SegmentSerial {
.follows_segment
.get_optional_nullable("follows_segment", || None)?;

if fixed_vram.is_some() && follows_segment.is_some() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "fixed_vram".to_string(),
field2: "follows_segment".to_string(),
});
let vram_class = self.vram_class.get_optional_nullable("vram_class", || None)?;

if fixed_vram.is_some() {
if follows_segment.is_some() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "fixed_vram".to_string(),
field2: "follows_segment".to_string(),
});
}

if vram_class.is_some() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "fixed_vram".to_string(),
field2: "vram_class".to_string(),
});
}
}

if follows_segment.is_some() {
if vram_class.is_some() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "follows_segment".to_string(),
field2: "vram_class".to_string(),
});
}
}

let alloc_sections = self
Expand Down Expand Up @@ -135,6 +160,7 @@ impl SegmentSerial {
files,
fixed_vram,
follows_segment,
vram_class,
alloc_sections,
noload_sections,
subalign,
Expand Down
61 changes: 61 additions & 0 deletions slinky/src/vram_class.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* SPDX-FileCopyrightText: © 2024 decompals */
/* SPDX-License-Identifier: MIT */

use serde::Deserialize;

use crate::{absent_nullable::AbsentNullable, Settings, SlinkyError};

#[derive(PartialEq, Debug)]
pub struct VramClass {
pub name: String,

pub fixed_vram: Option<u32>,

pub follows_classes: Vec<String>,
}

#[derive(Deserialize, PartialEq, Debug)]
#[serde(deny_unknown_fields)]
pub(crate) struct VramClassSerial {
pub name: String,

#[serde(default)]
pub fixed_vram: AbsentNullable<u32>,

#[serde(default)]
pub follows_classes: AbsentNullable<Vec<String>>,
}

impl VramClassSerial {
pub fn unserialize(self, _settings: &Settings) -> Result<VramClass, SlinkyError> {
if self.name.is_empty() {
return Err(SlinkyError::EmptyValue {
name: "name".to_string(),
});
}
let name = self.name;

let fixed_vram = self
.fixed_vram
.get_optional_nullable("fixed_vram", || None)?;

let follows_classes = self.follows_classes.get_non_null("follows_classes", || Vec::new())?;

if fixed_vram.is_some() && !follows_classes.is_empty() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "fixed_vram".into(),
field2: "follows_classes".into(),
});
}

if fixed_vram.is_none() && follows_classes.is_empty() {
return Err(SlinkyError::MissingAnyOfOptionalFields { fields: "'fixed_vram', 'follows_classes'".into() })
}

Ok(VramClass {
name,
fixed_vram,
follows_classes,
})
}
}
Loading

0 comments on commit a0ab1b9

Please sign in to comment.