memsolve 0.2.0

ROM memory layout solver for linker script generation
Documentation
use std::ops::Deref;

use crate::section::Section;

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Bin {
    bins: Vec<MemoryBin>,
}

impl Bin {
    pub(crate) fn new(bins: Vec<MemoryBin>) -> Self {
        Self { bins }
    }

    pub(crate) fn num_pages(&self) -> u64 {
        self.bins.iter().fold(0, |acc, b| acc + b.num_pages())
    }
}

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct MemoryBin {
    pub(crate) start_address: u64,
    pub(crate) end_address: u64,
    pub(crate) page_size: u64,
}

impl MemoryBin {
    pub(crate) fn num_pages(&self) -> u64 {
        (self.end_address - self.start_address) / self.page_size
    }

    pub(crate) fn space_until_end(&self, address: u64) -> u64 {
        if address > self.end_address || address < self.start_address {
            return 0;
        }
        self.end_address.saturating_sub(address)
    }

    pub(crate) fn pages_until_end(&self, address: u64) -> u64 {
        let space = self.space_until_end(address);
        space.strict_div(self.page_size)
    }

    pub(crate) fn section_fits_at_address<MetaData: Clone>(
        &self,
        address: u64,
        section: &Section<MetaData>,
    ) -> bool {
        if let Some(page_count) = section.pages
            && page_count > self.pages_until_end(address)
        {
            false
        } else if let Some(size) = section.size
            && size > self.space_until_end(address)
        {
            false
        } else {
            true
        }
    }
}

impl Deref for Bin {
    type Target = [MemoryBin];

    fn deref(&self) -> &Self::Target {
        self.bins.deref()
    }
}