use std::{fmt::Display, io::ErrorKind, marker::PhantomData, path::{Path, PathBuf}}; use crate::{ common::{Output, Relocatable}, error::Error, }; pub struct Linker<'data, R, O> where R: Relocatable<'data>, O: Output<'data>, { relocatables: Vec, output: O, _p: PhantomData<&'data ()>, } impl<'data, R, O> Linker<'data, R, O> where R: Relocatable<'data>, O: Output<'data>, { pub fn new(output: O) -> Self { Self { relocatables: Vec::new(), output, _p: PhantomData::default(), } } pub fn add_relocatable(&mut self, path: PathBuf) -> Result<(), Error> { self.relocatables.push(R::try_from(path)?); Ok(()) } pub fn link(&mut self) -> Result { for r in self.relocatables.iter() { for s in r.sections() { self.output.process_section(s?)?; } } self.output.finalize() } pub fn object_path(origin: &Path) -> Result { let mut dest = std::fs::canonicalize(origin)?; if !dest.pop() { let err = std::io::Error::new(ErrorKind::Other, "Destination path invalid"); Err(Error::IOError(Box::new(err))) } else { dest.push("rld.out"); Ok(dest) } } } impl<'data, R, O> Display for Linker<'data, R, O> where R: Relocatable<'data>, O: Output<'data>, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "===Relocatables===")?; for r in self.relocatables.iter() { write!(f, "{}", r)?; } Ok(()) } }