use std::{ collections::BTreeMap, fmt::{self, Display}, fs::File, io::{self, BufRead, BufReader, Read}, path::Path, }; #[derive(Debug)] pub struct Symbols { map: BTreeMap, } pub enum Error { Parse(ParseError), Io(io::Error), } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::Parse(inner) => inner.fmt(f), Error::Io(inner) => inner.fmt(f), } } } impl From for Error { fn from(error: io::Error) -> Self { Self::Io(error) } } pub enum ParseError { MalformedAddress, } impl Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseError::MalformedAddress => write!(f, "Malformed address"), } } } impl Symbols { pub fn from_path>(path: P) -> Result { let file = File::open(path)?; Self::from_read(file) } pub fn from_read(read: R) -> Result { let mut read = BufReader::new(read); let mut map = BTreeMap::new(); loop { let mut buf = [0; 2]; match read.read(&mut buf)? { 0 => break, 1 => return Err(Error::Parse(ParseError::MalformedAddress)), 2 => {} _ => unreachable!(), } let addr = u16::from_be_bytes(buf); let mut name = Vec::new(); read.read_until(b'\0', &mut name)?; name.pop(); // Pop '\0' let name = String::from_utf8_lossy(&name).to_string(); map.insert(addr, name); } Ok(Symbols { map }) } } impl Symbols { pub fn get(&self, addr: u16) -> Option<(&str, u16)> { self.map .range(..=addr) .rev() .next() .map(|(k, v)| (v.as_str(), *k)) } }