diff --git a/bff-cli/src/create.rs b/bff-cli/src/create.rs index 52a70ee..fff5eb0 100644 --- a/bff-cli/src/create.rs +++ b/bff-cli/src/create.rs @@ -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 { diff --git a/bff-cli/src/create_resource.rs b/bff-cli/src/create_resource.rs index f6b5402..927e348 100644 --- a/bff-cli/src/create_resource.rs +++ b/bff-cli/src/create_resource.rs @@ -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)?; } diff --git a/bff-cli/src/extract.rs b/bff-cli/src/extract.rs index 56ae19e..e1c7102 100644 --- a/bff-cli/src/extract.rs +++ b/bff-cli/src/extract.rs @@ -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>(()) diff --git a/bff-cli/src/extract_resource.rs b/bff-cli/src/extract_resource.rs index da8adcb..96706bb 100644 --- a/bff-cli/src/extract_resource.rs +++ b/bff-cli/src/extract_resource.rs @@ -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)?; diff --git a/bff/src/bigfile/mod.rs b/bff/src/bigfile/mod.rs index b10ca82..886d31e 100644 --- a/bff/src/bigfile/mod.rs +++ b/bff/src/bigfile/mod.rs @@ -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 { 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( - &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 diff --git a/bff/src/bigfile/resource.rs b/bff/src/bigfile/resource.rs index 6c8b0d5..5261aea 100644 --- a/bff/src/bigfile/resource.rs +++ b/bff/src/bigfile/resource.rs @@ -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 { + self.bff_resource_with_override(None, None, name_context) + } + + pub fn bff_resource_with_override( + &self, + platform_override: Option, + version_override: Option<&Version>, + name_context: &NameContext, + ) -> BffResult { + 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 { + self.bff_class_with_override(None, None, name_context) + } + + pub fn bff_class_with_override( + &self, + platform_override: Option, + version_override: Option<&Version>, + name_context: &NameContext, + ) -> BffResult { + 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(reader: &mut R, name_context: &NameContext) -> BffResult { let header = BffResourceHeader::read(reader)?; let resource = @@ -119,6 +172,14 @@ impl BffResourceRef<'_> { } } + pub fn bff_class(&self, name_context: &NameContext) -> BffResult { + let class = Class::from_resource(self.resource, self.version, self.platform, name_context)?; + Ok(BffClass { + header: self.header(), + class, + }) + } + pub fn write( &self, writer: &mut W, diff --git a/bff/src/macros/bigfiles.rs b/bff/src/macros/bigfiles.rs index fae052b..76368ff 100644 --- a/bff/src/macros/bigfiles.rs +++ b/bff/src/macros/bigfiles.rs @@ -192,43 +192,6 @@ macro_rules! bigfiles { } } - pub fn dump_bff_resource( - &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(); - ::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( reader: &mut R, platform: crate::bigfile::platforms::Platform, diff --git a/bff/tests/bigfile.rs b/bff/tests/bigfile.rs index 0153252..358ee09 100644 --- a/bff/tests/bigfile.rs +++ b/bff/tests/bigfile.rs @@ -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(