ds_rom/rom/raw/
overlay_table.rs

1use std::{borrow::Cow, fmt::Display};
2
3use crate::crypto::hmac_sha1::HmacSha1;
4
5use super::{HmacSha1Signature, Overlay};
6
7/// An overlay table, used for both ARM9 and ARM7 overlays. This is the raw struct, see the plain one [here](crate::rom::OverlayTable).
8pub struct OverlayTable<'a> {
9    overlays: Cow<'a, [Overlay]>,
10    signature: Option<HmacSha1Signature>,
11}
12
13impl<'a> OverlayTable<'a> {
14    /// Creates a new overlay table.
15    pub fn new<O>(overlays: O, signature: Option<HmacSha1Signature>) -> Self
16    where
17        O: Into<Cow<'a, [Overlay]>>,
18    {
19        Self { overlays: overlays.into(), signature }
20    }
21
22    /// Returns the overlays in the table.
23    pub fn overlays(&'a self) -> &'a [Overlay] {
24        self.overlays.as_ref()
25    }
26
27    /// Computes the HMAC-SHA1 signature of this overlay table using the given HMAC-SHA1 instance.
28    pub fn compute_signature(&self, hmac_sha1: &HmacSha1) -> HmacSha1Signature {
29        let bytes = bytemuck::cast_slice(&self.overlays);
30        HmacSha1Signature::from_hmac_sha1(hmac_sha1, bytes)
31    }
32
33    /// Verifies the HMAC-SHA1 signature of this overlay table using the given HMAC-SHA1 instance.
34    pub fn verify_signature(&self, hmac_sha1: &HmacSha1) -> bool {
35        let Some(signature) = self.signature() else {
36            return true;
37        };
38
39        let computed_signature = self.compute_signature(hmac_sha1);
40        computed_signature == signature
41    }
42
43    /// Returns the HMAC-SHA1 signature of the overlay table, if it exists.
44    pub fn signature(&self) -> Option<HmacSha1Signature> {
45        self.signature
46    }
47
48    /// Returns `true` if this overlay table has an HMAC-SHA1 signature.
49    pub fn is_signed(&self) -> bool {
50        self.signature.is_some()
51    }
52
53    /// Returns the raw bytes of the overlay table.
54    pub fn as_bytes(&self) -> &[u8] {
55        bytemuck::cast_slice(self.overlays.as_ref())
56    }
57
58    /// Returns a [`DisplayOverlayTable`] which implements [`Display`].
59    pub fn display(&'a self, indent: usize) -> DisplayOverlayTable<'a> {
60        DisplayOverlayTable { overlay_table: self, indent }
61    }
62}
63
64/// Can be used to display values in [`OverlayTable`].
65pub struct DisplayOverlayTable<'a> {
66    overlay_table: &'a OverlayTable<'a>,
67    indent: usize,
68}
69
70impl Display for DisplayOverlayTable<'_> {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        let i = " ".repeat(self.indent);
73        let overlay_table = &self.overlay_table;
74        let overlays = overlay_table.overlays();
75        let signature = overlay_table.signature().map_or("None".to_string(), |s| s.to_string());
76
77        writeln!(f, "{i}Overlay Table:")?;
78        writeln!(f, "{i}Signature: {}", signature)?;
79        writeln!(f, "{i}Overlays:")?;
80
81        for overlay in overlays {
82            writeln!(f, "{}", overlay.display(self.indent + 2))?;
83        }
84
85        Ok(())
86    }
87}