Clean up BffClass conversions

This commit is contained in:
widberg 2026-05-11 16:16:13 -04:00
parent 8e7686539e
commit 4dadb934fe
8 changed files with 122 additions and 155 deletions

View file

@ -5,10 +5,10 @@ use std::path::{Path, PathBuf};
use bff::bigfile::BigFile;
use bff::bigfile::platforms::Platform;
use bff::bigfile::resource::{BffClass, Resource};
use bff::bigfile::resource::{BffClass, BffResource, Resource};
use bff::bigfile::versions::Version;
use bff::names::{NameContext, NameType};
use bff::traits::{Artifact, Import, ToResource};
use bff::traits::{Artifact, Import};
use indicatif::{ProgressBar, ProgressStyle};
use crate::error::BffCliResult;
@ -114,15 +114,11 @@ pub fn create(
let _ = bff_class.class.import(&artifacts);
let platform = platform_override.unwrap_or(bff_class.header.platform);
let version = version_override
.as_ref()
.unwrap_or(&bff_class.header.version);
let resource: Resource =
bff_class
.class
.to_resource(version, platform, &name_context)?;
let BffResource { resource, .. } = bff_class.bff_resource_with_override(
*platform_override,
version_override.as_ref(),
&name_context,
)?;
if resources.contains_key(&resource.name) {
return Err(crate::error::BffCliError::DuplicateResource {

View file

@ -5,10 +5,10 @@ use std::path::{Path, PathBuf};
use bff::BufReader;
use bff::bigfile::platforms::Platform;
use bff::bigfile::resource::{BffClass, Resource};
use bff::bigfile::resource::BffClass;
use bff::bigfile::versions::Version;
use bff::names::{NameContext, NameType};
use bff::traits::{Artifact, Import, ToResource};
use bff::traits::{Artifact, Import};
use crate::error::BffCliResult;
use crate::extract::write_names;
@ -84,24 +84,15 @@ pub fn create_resource(
let _ = bff_class.class.import(&artifacts);
let platform = platform_override.unwrap_or(bff_class.header.platform);
let version = version_override
.as_ref()
.unwrap_or(&bff_class.header.version);
let resource: Resource = bff_class
.class
.to_resource(version, platform, &name_context)?;
let mut resource_writer = BufWriter::new(File::create(resource_path)?);
Resource::dump_bff_resource(
&resource,
&mut resource_writer,
platform,
version,
let bff_resource = bff_class.bff_resource_with_override(
*platform_override,
version_override.as_ref(),
&name_context,
)?;
let mut resource_writer = BufWriter::new(File::create(resource_path)?);
bff_resource.write(&mut resource_writer, &name_context)?;
if let Some(out_names) = out_names {
write_names(out_names, None, &name_context)?;
}

View file

@ -5,11 +5,10 @@ use std::path::{Path, PathBuf};
use bff::BufReader;
use bff::bigfile::BigFile;
use bff::bigfile::platforms::{Platform, try_platform_style_to_name_extension};
use bff::bigfile::resource::{BffClass, BffResourceHeader, Resource};
use bff::bigfile::resource::BffResourceRef;
use bff::bigfile::versions::Version;
use bff::class::Class;
use bff::names::{Name, NameContext};
use bff::traits::{Artifact, Export, FromResource};
use bff::traits::{Artifact, Export};
use clap::ValueEnum;
use indicatif::{ProgressBar, ProgressStyle};
use rayon::iter::{ParallelBridge, ParallelIterator};
@ -127,13 +126,20 @@ fn strip_suffix_if_exists(s: String, suffix: &str) -> String {
fn dump_bff_resource(
resources_path: &Path,
bigfile: &BigFile,
resource: &Resource,
bff_resource: &BffResourceRef,
name_context: &NameContext,
) -> BffCliResult<()> {
let class_name = resource.class_name.with_context(name_context).to_string();
let class_name = bff_resource
.resource
.class_name
.with_context(name_context)
.to_string();
let name = clean_path(strip_suffix_if_exists(
resource.name.with_context(name_context).to_string(),
bff_resource
.resource
.name
.with_context(name_context)
.to_string(),
&format!(".{}", class_name),
));
let mut path = resources_path.join(format!("{}.{}", name, class_name));
@ -143,30 +149,29 @@ fn dump_bff_resource(
i += 1;
}
let mut writer = BufWriter::new(File::create(path)?);
bigfile.dump_bff_resource(resource, &mut writer, name_context)?;
bff_resource.write(&mut writer, name_context)?;
Ok(())
}
fn export_bff_resource(
resources_path: &Path,
bigfile: &BigFile,
resource: &Resource,
bff_resource: &BffResourceRef,
name_context: &NameContext,
rich_suffix: &String,
) -> BffCliResult<()> {
let platform = bigfile.manifest().platform;
let version = &bigfile.manifest().version;
let header = BffResourceHeader {
platform,
version: version.clone(),
};
let bff_class = bff_resource.bff_class(name_context)?;
let class: Class = Class::from_resource(resource, version, platform, name_context)?;
let bff_class = BffClass { header, class };
let class_name = resource.class_name.with_context(name_context).to_string();
let class_name = bff_resource
.resource
.class_name
.with_context(name_context)
.to_string();
let name = clean_path(strip_suffix_if_exists(
resource.name.with_context(name_context).to_string(),
bff_resource
.resource
.name
.with_context(name_context)
.to_string(),
&format!(".{}", class_name),
));
let mut directory = resources_path.join(format!("{}.{}{}", name, class_name, rich_suffix));
@ -243,21 +248,10 @@ pub fn extract(
.try_for_each(|bff_resource| {
progress_bar.inc(1);
if !matches!(*export_strategy, ExportStrategy::Rich)
|| export_bff_resource(
&resources_path,
&bigfile,
bff_resource.resource,
&name_context,
rich_suffix,
)
.is_err()
|| export_bff_resource(&resources_path, &bff_resource, &name_context, rich_suffix)
.is_err()
{
dump_bff_resource(
&resources_path,
&bigfile,
bff_resource.resource,
&name_context,
)?;
dump_bff_resource(&resources_path, &bff_resource, &name_context)?;
}
Ok::<(), BffCliError>(())

View file

@ -4,11 +4,10 @@ use std::path::{Path, PathBuf};
use bff::BufReader;
use bff::bigfile::platforms::Platform;
use bff::bigfile::resource::{BffClass, BffResource, BffResourceHeader};
use bff::bigfile::resource::{BffResource, BffResourceHeader};
use bff::bigfile::versions::Version;
use bff::class::Class;
use bff::names::{NameContext, NameType};
use bff::traits::{Artifact, Export, FromResource};
use bff::traits::{Artifact, Export};
use crate::error::BffCliResult;
use crate::extract::read_in_names;
@ -48,18 +47,11 @@ pub fn extract_resource(
let mut reader = BufReader::new(f);
let bff_resource = BffResource::read(&mut reader, &name_context)?;
let platform = platform_override.unwrap_or(bff_resource.header.platform);
let version = version_override
.as_ref()
.unwrap_or(&bff_resource.header.version);
let header = BffResourceHeader {
platform,
version: version.clone(),
};
let class: Class =
Class::from_resource(&bff_resource.resource, version, platform, &name_context)?;
let bff_class = BffClass { header, class };
let bff_class = bff_resource.bff_class_with_override(
*platform_override,
version_override.as_ref(),
&name_context,
)?;
std::fs::create_dir(directory)?;

View file

@ -35,10 +35,9 @@ use crate::bigfile::v2_07_pc::{BigFileV2_07PCPROTO, BigFileV2_07PCSHAUN};
use crate::bigfile::v2_128_52_19_pc::BigFileV2_128_52_19PC;
use crate::bigfile::v2_128_92_19_pc::BigFileV2_128_92_19PC;
use crate::bigfile::v2_256_38_19_pc::BigFileV2_256_38_19PC;
use crate::class::Class;
use crate::macros::bigfiles::bigfiles;
use crate::names::{Name, NameContext};
use crate::traits::{FromResource, ReferencedNames};
use crate::traits::ReferencedNames;
pub static DEFAULT_TAG: &str = "made with <3 by bff contributors (https://github.com/widberg/bff)";
@ -95,15 +94,12 @@ impl BigFile {
pub fn reference_graph(&self, name_context: &NameContext) -> Graph<Name, ()> {
let mut graph = Graph::with_capacity(self.resources.len(), 0);
let mut node_ids = HashMap::new();
for (&name, resource) in &self.resources {
let references = Class::from_resource(
resource,
&self.manifest.version,
self.manifest.platform,
name_context,
)
.map(|class| class.referenced_names())
.unwrap_or_default();
for bff_resource in self.bff_resources() {
let name = bff_resource.resource.name;
let references = bff_resource
.bff_class(name_context)
.map(|bff_class| bff_class.class.referenced_names())
.unwrap_or_default();
let from_id = *node_ids.entry(name).or_insert_with(|| graph.add_node(name));
for reference in references {
let to_id = *node_ids
@ -132,23 +128,6 @@ impl BigFile {
let version = version_override.clone().unwrap_or(version);
version.name_type()
}
pub fn dump_bff_resource<W: std::io::Write + std::io::Seek>(
&self,
resource: &crate::bigfile::resource::Resource,
writer: &mut W,
name_context: &crate::names::NameContext,
) -> crate::BffResult<()> {
let platform = self.manifest.platform;
let version = &self.manifest.version;
crate::bigfile::resource::Resource::dump_bff_resource(
resource,
writer,
platform,
version,
name_context,
)
}
}
// TODO: All this type stuff is nonsense. Just have modules and re-check the bf

View file

@ -9,6 +9,7 @@ use super::versions::Version;
use crate::BffResult;
use crate::class::Class;
use crate::names::{Name, NameContext, NameType};
use crate::traits::{FromResource, ToResource};
#[derive(Debug, Eq, PartialEq)]
pub enum ResourceData {
@ -87,7 +88,59 @@ pub struct BffResourceRef<'a> {
pub resource: &'a Resource,
}
impl BffClass {
pub fn bff_resource(&self, name_context: &NameContext) -> BffResult<BffResource> {
self.bff_resource_with_override(None, None, name_context)
}
pub fn bff_resource_with_override(
&self,
platform_override: Option<Platform>,
version_override: Option<&Version>,
name_context: &NameContext,
) -> BffResult<BffResource> {
let platform = platform_override.unwrap_or(self.header.platform);
let version = version_override.unwrap_or(&self.header.version);
let resource = self.class.to_resource(version, platform, name_context)?;
Ok(BffResource {
header: BffResourceHeader {
platform,
version: version.clone(),
},
resource,
})
}
}
impl BffResource {
pub const fn as_ref(&self) -> BffResourceRef<'_> {
BffResourceRef {
platform: self.header.platform,
version: &self.header.version,
resource: &self.resource,
}
}
pub fn bff_class(&self, name_context: &NameContext) -> BffResult<BffClass> {
self.bff_class_with_override(None, None, name_context)
}
pub fn bff_class_with_override(
&self,
platform_override: Option<Platform>,
version_override: Option<&Version>,
name_context: &NameContext,
) -> BffResult<BffClass> {
let platform = platform_override.unwrap_or(self.header.platform);
let version = version_override.unwrap_or(&self.header.version);
BffResourceRef {
platform,
version,
resource: &self.resource,
}
.bff_class(name_context)
}
pub fn read<R: Read + Seek>(reader: &mut R, name_context: &NameContext) -> BffResult<Self> {
let header = BffResourceHeader::read(reader)?;
let resource =
@ -119,6 +172,14 @@ impl BffResourceRef<'_> {
}
}
pub fn bff_class(&self, name_context: &NameContext) -> BffResult<BffClass> {
let class = Class::from_resource(self.resource, self.version, self.platform, name_context)?;
Ok(BffClass {
header: self.header(),
class,
})
}
pub fn write<W: Write + Seek>(
&self,
writer: &mut W,

View file

@ -192,43 +192,6 @@ macro_rules! bigfiles {
}
}
pub fn dump_bff_resource<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
platform: crate::bigfile::platforms::Platform,
version: &crate::bigfile::versions::Version,
name_context: &crate::names::NameContext,
) -> crate::BffResult<()> {
use crate::bigfile::versions::Version::*;
use crate::traits::BigFileIo;
let endian: crate::Endian = platform.into();
<crate::bigfile::resource::BffResourceHeader as binrw::BinWrite>::write(
&crate::bigfile::resource::BffResourceHeader {
platform,
version: version.clone(),
},
writer,
)?;
let resource = self;
match version {
$($version_pattern => {
if name_context.name_type() != <$bigfile as BigFileIo>::NAME_TYPE {
return Err(std::io::Error::other(format!(
"NameContext type mismatch: expected {:?}, got {:?}",
<$bigfile as BigFileIo>::NAME_TYPE,
name_context.name_type()
))
.into());
}
name_context.scope(|| {
Ok(<$bigfile as BigFileIo>::ResourceType::dump_resource(resource, writer, endian)?)
})
})*
_ => Err(crate::error::UnimplementedVersionError::new(version.clone()).into()),
}
}
pub fn read_resource<R: std::io::Read + std::io::Seek>(
reader: &mut R,
platform: crate::bigfile::platforms::Platform,

View file

@ -4,10 +4,9 @@ use std::io::Cursor;
use bff::bigfile::BigFile;
use bff::bigfile::platforms::Platform;
use bff::bigfile::resource::{BffClass, BffResourceHeader, Resource};
use bff::class::Class;
use bff::bigfile::resource::{BffClass, Resource};
use bff::names::NameContext;
use bff::traits::{Export, FromResource, Import, ToResource};
use bff::traits::{Export, Import, ToResource};
use binrw::io::BufReader;
use crate::path_helpers::resolve_bigfile_path;
@ -64,15 +63,7 @@ fn roundtrip_resources(bigfile_path_str: String) {
let version = &bigfile.manifest().version;
for bff_resource in bigfile.bff_resources() {
let class: Class =
Class::from_resource(bff_resource.resource, version, platform, &name_context).unwrap();
let bff_class = BffClass {
header: BffResourceHeader {
platform,
version: version.clone(),
},
class,
};
let bff_class = bff_resource.bff_class(&name_context).unwrap();
let resource_serialized =
bff::names::json::to_string_pretty(&bff_class, &name_context).unwrap();
let mut roundtripped_bff_class: BffClass = bff::names::json::from_reader(