Skip to content

Commit

Permalink
Revises metadata parser
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon committed Oct 14, 2024
1 parent 329ab4f commit 5cd1877
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 50 deletions.
71 changes: 29 additions & 42 deletions macros/src/meta.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use self::ty::*;

use crate::symbol::{Segment, Symbol, TemplateArg};
use crate::symbol::Symbol;
use memmap2::Mmap;
use object::read::archive::ArchiveFile;
use std::collections::HashMap;
Expand All @@ -20,47 +20,24 @@ impl Metadata {
// Open file.
let file = File::open(path).map_err(MetadataError::OpenFileFailed)?;
let file = unsafe { Mmap::map(&file).map_err(MetadataError::MapFileFailed) }?;
let file = ArchiveFile::parse(file.as_ref()).map_err(MetadataError::ParseFileFailed)?;
let ar = ArchiveFile::parse(file.as_ref()).map_err(MetadataError::ParseFileFailed)?;

// Get symbols.
let symbols = file.symbols().map_err(MetadataError::GetSymbolsFailed)?;
// Parse members.
let mut types = HashMap::new();
let symbols = match symbols {
Some(v) => v,
None => return Ok(Self { types }),
};

// Parse symbols.
for sym in symbols {
let sym = sym.map_err(MetadataError::ReadSymbolFailed)?;
let sym = match Symbol::parse(sym.name()) {
Ok(v) => v,
Err(_) => continue, // Ignore unknown symbol.
};

// Check namespace.
let mut iter = sym.name().iter();
let ns = iter.next();

if !ns.is_some_and(|s| *s == Segment::Ident("cppbind".into())) {
continue;
}

// Check metadata type.
let ty = iter.next();

if !ty.is_some_and(|s| *s == Segment::Ident("type_info".into())) {
continue;
for (i, mem) in ar.members().enumerate() {
let mem = mem.map_err(|e| MetadataError::ParseMemberHeaderFailed(i, e))?;
let mem = mem
.data(file.as_ref())
.map_err(|e| MetadataError::GetMemberDataFailed(i, e))?;

if mem.starts_with(b"\x7FELF") {
Self::parse_elf(&mut types)?;
} else {
return Err(MetadataError::UnknownMember(
mem.iter().take(4).map(|v| *v).collect(),
));
}

// Get class name.
let ty = iter.next().expect("invalid cppbind::type_info definition");
let class = match ty {
Segment::Ident(_) => panic!("invalid argument for cppbind::type_info"),
Segment::TemplateArg(TemplateArg::Ident(v)) => v,
};

types.insert(class.clone().into_owned(), TypeInfo::new());
}

Ok(Self { types })
Expand All @@ -69,6 +46,10 @@ impl Metadata {
pub fn get_type(&self, name: impl AsRef<str>) -> Option<&TypeInfo> {
self.types.get(name.as_ref())
}

fn parse_elf(_: &mut HashMap<String, TypeInfo>) -> Result<(), MetadataError> {
todo!("ELF parser")
}
}

/// Represents an error when [`Metadata`] fails to load.
Expand All @@ -83,9 +64,15 @@ pub enum MetadataError {
#[error("couldn't parse the specified file")]
ParseFileFailed(#[source] object::read::Error),

#[error("couldn't get available symbols")]
GetSymbolsFailed(#[source] object::read::Error),
#[error("couldn't parse header for member #{0}")]
ParseMemberHeaderFailed(usize, #[source] object::read::Error),

#[error("couldn't get data for member #{0}")]
GetMemberDataFailed(usize, #[source] object::read::Error),

#[error("unknown member ({0:x?})")]
UnknownMember(Vec<u8>),

#[error("couldn't read a symbol")]
ReadSymbolFailed(#[source] object::read::Error),
#[error("unknown symbol in cppbind namespace")]
UnknownDefinition(Symbol),
}
9 changes: 3 additions & 6 deletions macros/src/meta/ty.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
/// Contains information for a C++ class.
pub struct TypeInfo {}

impl TypeInfo {
pub(super) fn new() -> Self {
Self {}
}
#[derive(Default)]
pub struct TypeInfo {
pub size: Option<usize>,
}
5 changes: 3 additions & 2 deletions macros/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use thiserror::Error;
mod itanium;

/// C++ symbol.
#[derive(Debug)]
pub struct Symbol {
name: Vec<Segment<'static>>,
}
Expand All @@ -25,14 +26,14 @@ impl Symbol {
}

/// Segment of a C++ name.
#[derive(PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq)]
pub enum Segment<'a> {
Ident(Cow<'a, str>),
TemplateArg(TemplateArg<'a>),
}

/// Argument of a template instantiation.
#[derive(PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq)]
pub enum TemplateArg<'a> {
Ident(Cow<'a, str>),
}
Expand Down

0 comments on commit 5cd1877

Please sign in to comment.