use std::borrow::Cow;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::path::Path;
mod magic;
mod objects;
mod parser;
pub use objects::{CodeObject, Object, ObjectType, StringType};
pub use parser::{Error, MarshalObject};
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct MarshalFile {
data: Vec<u8>,
marshal: MarshalObject,
}
impl MarshalFile {
pub fn from_pyc_path<S>(path: S) -> Result<Self>
where
S: AsRef<Path>,
{
let mut file = OpenOptions::new()
.read(true)
.write(false)
.create_new(false)
.open(path)?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
let marshal = MarshalObject::parse_pyc(&data)?;
Ok(MarshalFile { data, marshal })
}
pub fn from_dump_path<S>(path: S, (major, minor): (u16, u16)) -> Result<Self>
where
S: AsRef<Path>,
{
let mut file = OpenOptions::new()
.read(true)
.write(false)
.create_new(false)
.open(path)?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
let marshal = MarshalObject::parse_dump(&data, (major, minor))?;
Ok(MarshalFile { data, marshal })
}
pub fn inner(&self) -> &Object {
&self.marshal.object
}
pub fn into_inner(self) -> Object {
self.marshal.object
}
pub fn print_unused_ref_flags(&self) {
self.marshal.print_unused_ref_flags();
}
pub fn write_normalized<S>(self, path: S) -> Result<bool>
where
S: AsRef<Path>,
{
let marshal = self.marshal;
let result = marshal.clear_unused_ref_flags(&self.data)?;
if let Cow::Owned(x) = result {
let mut file = File::create_new(path)?;
file.write_all(&x)?;
Ok(true)
} else {
Ok(false)
}
}
}