mirror of
https://github.com/widberg/bff
synced 2026-08-23 14:26:03 -04:00
[Core] Make proc macros into declarative macros
This commit is contained in:
parent
acc235163b
commit
c25918d9b6
84 changed files with 525 additions and 811 deletions
|
|
@ -32,3 +32,4 @@ panic = "abort"
|
|||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
debug = 0
|
||||
|
|
|
|||
|
|
@ -1,308 +0,0 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Arm, Attribute, Ident, Result, braced};
|
||||
|
||||
pub struct BffClassMacroInput {
|
||||
class: Ident,
|
||||
forms: Vec<Arm>,
|
||||
has_generic: bool,
|
||||
}
|
||||
|
||||
impl Parse for BffClassMacroInput {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let attrs: Vec<Attribute> = input.call(Attribute::parse_inner)?;
|
||||
let has_generic = !attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path().is_ident("generic"))
|
||||
.collect::<Vec<_>>()
|
||||
.is_empty();
|
||||
let class = input.parse()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let mut forms = Vec::new();
|
||||
while !content.is_empty() {
|
||||
forms.push(content.parse()?);
|
||||
}
|
||||
Ok(Self {
|
||||
class,
|
||||
forms,
|
||||
has_generic,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive_bff_class(input: BffClassMacroInput) -> TokenStream {
|
||||
let enum_class = impl_enum_class(&input);
|
||||
|
||||
let from_object_to_shadow_class = impl_from_object_to_shadow_class(&input);
|
||||
let from_shadow_class_to_object = impl_from_shadow_class_to_object(&input);
|
||||
let from_shadow_class_to_generic = impl_from_shadow_class_to_generic(&input);
|
||||
let try_your_best = impl_try_your_best(&input);
|
||||
|
||||
if input.has_generic {
|
||||
quote! {
|
||||
#enum_class
|
||||
#from_object_to_shadow_class
|
||||
#from_shadow_class_to_object
|
||||
#from_shadow_class_to_generic
|
||||
#try_your_best
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#enum_class
|
||||
#from_object_to_shadow_class
|
||||
#from_shadow_class_to_object
|
||||
#try_your_best
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_enum_class(input: &BffClassMacroInput) -> proc_macro2::TokenStream {
|
||||
let class = &input.class;
|
||||
|
||||
let variants = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let body = &form.body;
|
||||
quote! { #body(std::boxed::Box<#body>) }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let import_export = if input.forms.is_empty() {
|
||||
quote! {
|
||||
impl crate::traits::Export for #class {}
|
||||
impl crate::traits::Import for #class {}
|
||||
}
|
||||
} else {
|
||||
let arms_export = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let body = &form.body;
|
||||
quote! { #class::#body(class) => <#body as crate::traits::Export>::export(class) }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let arms_import = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let body = &form.body;
|
||||
quote! { #class::#body(class) => <#body as crate::traits::Import>::import(class, artifacts) }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
impl crate::traits::Export for #class {
|
||||
fn export(&self) -> crate::BffResult<std::collections::HashMap<std::ffi::OsString, crate::traits::Artifact>> {
|
||||
match self {
|
||||
#(#arms_export,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::Import for #class {
|
||||
fn import(&mut self, artifacts: &std::collections::HashMap<std::ffi::OsString, crate::traits::Artifact>) -> crate::BffResult<()> {
|
||||
match self {
|
||||
#(#arms_import,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, bff_derive::NamedClass, derive_more::From, derive_more::IsVariant, bff_derive::ReferencedNames)]
|
||||
pub enum #class {
|
||||
#(#variants),*
|
||||
}
|
||||
|
||||
#import_export
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_try_your_best(input: &BffClassMacroInput) -> proc_macro2::TokenStream {
|
||||
let class = &input.class;
|
||||
|
||||
let variants = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| &form.body)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let report_struct = quote::format_ident!("{}TryYourBestReport", class);
|
||||
|
||||
quote! {
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct #report_struct {
|
||||
pub total: usize,
|
||||
#(#variants: usize),*
|
||||
}
|
||||
|
||||
impl crate::traits::TryYourBest<&crate::bigfile::resource::Resource> for #class {
|
||||
type Report = #report_struct;
|
||||
fn update_report(resource: &crate::bigfile::resource::Resource, platform: crate::bigfile::platforms::Platform, report: &mut Self::Report) {
|
||||
report.total += 1;
|
||||
// TODO: Probably need a way to do this without specifying a version.
|
||||
#(
|
||||
report.#variants += <bool as Into<usize>>::into(<&crate::bigfile::resource::Resource as crate::traits::TryIntoVersionPlatform<#variants>>::try_into_version_platform(resource, crate::bigfile::versions::Version::Asobo(0, 0, 0, 0), platform).is_ok());
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #report_struct {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", stringify!(#class))?;
|
||||
writeln!(f, "Total: {}", self.total)?;
|
||||
#(
|
||||
writeln!(f, "{}: {}", stringify!(#variants), self.#variants)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_from_object_to_shadow_class(input: &BffClassMacroInput) -> proc_macro2::TokenStream {
|
||||
let class = &input.class;
|
||||
|
||||
let arms = input.forms.iter().map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => {
|
||||
let shadow_class: #body = <&crate::bigfile::resource::Resource as crate::traits::TryIntoVersionPlatform<#body>>::try_into_version_platform(object, version, platform)?;
|
||||
Ok(std::boxed::Box::new(shadow_class).into())
|
||||
}
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let body = if arms.is_empty() {
|
||||
quote! {
|
||||
todo!()
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
_ => Err(
|
||||
// TODO: Pick the right name based on the algorithm and suffix for the current BigFile
|
||||
crate::error::UnimplementedClassError::new(object.name, <Self as crate::traits::NamedClass<crate::names::NameAsobo32>>::NAME.into(), version, platform).into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl crate::traits::TryFromVersionPlatform<&crate::bigfile::resource::Resource> for #class {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
fn try_from_version_platform(
|
||||
object: &crate::bigfile::resource::Resource,
|
||||
version: crate::bigfile::versions::Version,
|
||||
platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<#class> {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_from_shadow_class_to_object(input: &BffClassMacroInput) -> proc_macro2::TokenStream {
|
||||
let class = &input.class;
|
||||
|
||||
let arms = input.forms.iter().map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#class::#body(class) => {
|
||||
let object: crate::bigfile::resource::Resource = <&#body as crate::traits::TryIntoVersionPlatform<crate::bigfile::resource::Resource>>::try_into_version_platform(class, version, platform)?;
|
||||
Ok(object)
|
||||
}
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let body = if arms.is_empty() {
|
||||
quote! {
|
||||
todo!()
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
match class {
|
||||
#(#arms)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl crate::traits::TryFromVersionPlatform<&#class> for crate::bigfile::resource::Resource {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
fn try_from_version_platform(
|
||||
class: &#class,
|
||||
version: crate::bigfile::versions::Version,
|
||||
platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_from_shadow_class_to_generic(input: &BffClassMacroInput) -> proc_macro2::TokenStream {
|
||||
let class = &input.class;
|
||||
let generic_class_str = format!("{}Generic", class);
|
||||
let generic_class = Ident::new(&generic_class_str, generic_class_str.span());
|
||||
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#class::#body(class) => {
|
||||
(*class).into()
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let body = if arms.is_empty() {
|
||||
quote! {
|
||||
todo!()
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
match class {
|
||||
#(#arms)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl From<#class> for generic::#generic_class {
|
||||
fn from(
|
||||
class: #class,
|
||||
) -> generic::#generic_class {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,364 +0,0 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::{Arm, Result};
|
||||
|
||||
pub struct BffBigFileMacroInput {
|
||||
forms: Vec<Arm>,
|
||||
}
|
||||
|
||||
impl Parse for BffBigFileMacroInput {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let mut forms = Vec::new();
|
||||
while !input.is_empty() {
|
||||
forms.push(input.parse()?);
|
||||
}
|
||||
Ok(Self { forms })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive_bigfiles(input: BffBigFileMacroInput) -> TokenStream {
|
||||
let try_your_best_bigfile = impl_try_your_best_bigfile(&input);
|
||||
let read_bigfile = impl_read_bigfile(&input);
|
||||
let write_bigfile = impl_write_bigfile(&input);
|
||||
let (dump_resource, dump_resource_resource) = impl_dump_resource(&input);
|
||||
let (read_resource, read_resource_resource) = impl_read_resource(&input);
|
||||
let version_into_name_type = impl_version_into_name_type(&input);
|
||||
|
||||
quote! {
|
||||
impl BigFile {
|
||||
#read_bigfile
|
||||
#write_bigfile
|
||||
#dump_resource
|
||||
#read_resource
|
||||
}
|
||||
|
||||
#try_your_best_bigfile
|
||||
|
||||
impl crate::bigfile::resource::Resource {
|
||||
#dump_resource_resource
|
||||
#read_resource_resource
|
||||
}
|
||||
|
||||
#version_into_name_type
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_try_your_best_bigfile(input: &BffBigFileMacroInput) -> proc_macro2::TokenStream {
|
||||
let variants = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| &form.body)
|
||||
.collect::<Vec<_>>();
|
||||
quote! {
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct BigFileTryYourBestReport {
|
||||
pub total: usize,
|
||||
#(#variants: usize),*
|
||||
}
|
||||
|
||||
impl<R: std::io::Read + std::io::Seek> crate::traits::TryYourBest<&mut R> for BigFile {
|
||||
type Report = BigFileTryYourBestReport;
|
||||
fn update_report(reader: &mut R, platform: crate::bigfile::platforms::Platform, report: &mut Self::Report) {
|
||||
use crate::traits::BigFileIo;
|
||||
report.total += 1;
|
||||
// TODO: Probably need a way to do this without specifying a version.
|
||||
#(
|
||||
reader.seek(std::io::SeekFrom::Start(256)).unwrap();
|
||||
report.#variants += {crate::names::names().lock().unwrap().name_type = <#variants as BigFileIo>::NAME_TYPE;
|
||||
<bool as Into<usize>>::into(<#variants as BigFileIo>::read(reader, crate::bigfile::versions::Version::Asobo(0, 0, 0, 0), platform).is_ok())};
|
||||
)*
|
||||
reader.rewind().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BigFileTryYourBestReport {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "BigFile")?;
|
||||
writeln!(f, "Total: {}", self.total)?;
|
||||
#(
|
||||
writeln!(f, "{}: {}", stringify!(#variants), self.#variants)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_read_bigfile(input: &BffBigFileMacroInput) -> proc_macro2::TokenStream {
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => {
|
||||
crate::names::names().lock().unwrap().name_type = <#body as BigFileIo>::NAME_TYPE;
|
||||
<#body as BigFileIo>::read(reader, version, platform)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
pub fn read_platform<R: std::io::Read + std::io::Seek>(reader: &mut R, platform: crate::bigfile::platforms::Platform, version_override: &Option<crate::bigfile::versions::Version>) -> crate::BffResult<Self> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use binrw::BinRead;
|
||||
use crate::traits::BigFileIo;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version: crate::bigfile::versions::Version = crate::helpers::FixedStringNull::<256>::read_be(reader)?.as_str().into();
|
||||
let version = version_override.clone().unwrap_or(version);
|
||||
match (&version, platform) {
|
||||
#(#arms)*
|
||||
_ => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_write_bigfile(input: &BffBigFileMacroInput) -> proc_macro2::TokenStream {
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => {
|
||||
crate::names::names().lock().unwrap().name_type = <#body as BigFileIo>::NAME_TYPE;
|
||||
<#body as BigFileIo>::write(self, writer, tag)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
pub fn write<W: std::io::Write + std::io::Seek>(&self, writer: &mut W, platform_override: Option<crate::bigfile::platforms::Platform>, version_override: &Option<crate::bigfile::versions::Version>, tag: Option<&str>) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use binrw::BinWrite;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = platform_override.unwrap_or(self.manifest.platform);
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
let version = version_override.as_ref().unwrap_or(version);
|
||||
let version_string = version.to_string();
|
||||
crate::helpers::FixedStringNull::<256>::write_be(&version_string.into(), writer)?;
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_dump_resource(
|
||||
input: &BffBigFileMacroInput,
|
||||
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => {
|
||||
crate::names::names().lock().unwrap().name_type = <#body as BigFileIo>::NAME_TYPE;
|
||||
Ok(<#body as BigFileIo>::ResourceType::dump_resource(resource, writer, endian)?)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(
|
||||
quote! {
|
||||
pub fn dump_resource<W: std::io::Write + std::io::Seek>(&self, resource: &crate::bigfile::resource::Resource, writer: &mut W) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = self.manifest.platform;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_bff_resource<W: std::io::Write + std::io::Seek>(&self, resource: &crate::bigfile::resource::Resource, writer: &mut W) -> crate::BffResult<()> {
|
||||
let platform = self.manifest.platform;
|
||||
let version = &self.manifest.version;
|
||||
crate::bigfile::resource::Resource::dump_bff_resource(resource, writer, platform, version)
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
pub fn dump_resource<W: std::io::Write + std::io::Seek>(&self, writer: &mut W, platform: crate::bigfile::platforms::Platform, version: &crate::bigfile::versions::Version) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let resource = self;
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
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) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
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.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn impl_read_resource(
|
||||
input: &BffBigFileMacroInput,
|
||||
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => {
|
||||
crate::names::names().lock().unwrap().name_type = <#body as BigFileIo>::NAME_TYPE;
|
||||
Ok(<#body as BigFileIo>::ResourceType::read_resource(reader, endian)?)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(
|
||||
quote! {
|
||||
pub fn read_resource<R: std::io::Read + std::io::Seek>(&self, reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = self.manifest.platform;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
pub fn read_bff_resource<R: std::io::Read + std::io::Seek>(&self, reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let crate::bigfile::resource::BffResourceHeader {
|
||||
platform,
|
||||
version,
|
||||
} = <crate::bigfile::resource::BffResourceHeader as binrw::BinRead>::read(reader)?;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
pub fn read_resource<R: std::io::Read + std::io::Seek>(reader: &mut R, platform: crate::bigfile::platforms::Platform, version: &crate::bigfile::versions::Version) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_bff_resource<R: std::io::Read + std::io::Seek>(reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let crate::bigfile::resource::BffResourceHeader {
|
||||
platform,
|
||||
version,
|
||||
} = <crate::bigfile::resource::BffResourceHeader as binrw::BinRead>::read(reader)?;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn impl_version_into_name_type(input: &BffBigFileMacroInput) -> proc_macro2::TokenStream {
|
||||
let arms = input
|
||||
.forms
|
||||
.iter()
|
||||
.map(|form| {
|
||||
let attrs = &form.attrs;
|
||||
let pat = &form.pat;
|
||||
let guard = match &form.guard {
|
||||
Some((_, guard)) => quote! { #guard },
|
||||
None => quote! {},
|
||||
};
|
||||
let body = &form.body;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
#pat #guard => Ok(<#body as BigFileIo>::NAME_TYPE),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
impl TryFrom<&crate::bigfile::versions::Version> for crate::names::NameType {
|
||||
type Error = crate::BffError;
|
||||
|
||||
fn try_from(version: &crate::bigfile::versions::Version) -> Result<crate::names::NameType, Self::Error> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
match (version.clone(), PC) {
|
||||
#(#arms)*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionError::new(version).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +1,19 @@
|
|||
use proc_macro::TokenStream;
|
||||
use syn::{DeriveInput, parse_macro_input};
|
||||
|
||||
use crate::bff_class::{BffClassMacroInput, derive_bff_class};
|
||||
use crate::bigfiles::{BffBigFileMacroInput, derive_bigfiles};
|
||||
use crate::generic_class::derive_generic_class;
|
||||
use crate::named_class::derive_named_class;
|
||||
use crate::referenced_names::derive_referenced_names;
|
||||
use crate::trivial_class::{TrivialClassMacroInput, derive_trivial_class};
|
||||
|
||||
mod bff_class;
|
||||
mod bigfiles;
|
||||
mod generic_class;
|
||||
mod named_class;
|
||||
mod referenced_names;
|
||||
mod trivial_class;
|
||||
|
||||
#[proc_macro_derive(NamedClass)]
|
||||
pub fn named_class(input: TokenStream) -> TokenStream {
|
||||
derive_named_class(parse_macro_input!(input as DeriveInput)).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(GenericClass, attributes(generic))]
|
||||
pub fn generic_class(input: TokenStream) -> TokenStream {
|
||||
derive_generic_class(parse_macro_input!(input as DeriveInput)).into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn bff_class(input: TokenStream) -> TokenStream {
|
||||
derive_bff_class(parse_macro_input!(input as BffClassMacroInput)).into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn bigfiles(input: TokenStream) -> TokenStream {
|
||||
derive_bigfiles(parse_macro_input!(input as BffBigFileMacroInput)).into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn trivial_class(input: TokenStream) -> TokenStream {
|
||||
derive_trivial_class(parse_macro_input!(input as TrivialClassMacroInput)).into()
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{DeriveInput, LitStr};
|
||||
|
||||
pub fn derive_named_class(input: DeriveInput) -> TokenStream {
|
||||
let name = &input.ident;
|
||||
let class_name = LitStr::new(format!("{}_Z", name).as_str(), name.span());
|
||||
let class_name_legacy = LitStr::new(&name.to_string().to_uppercase(), name.span());
|
||||
|
||||
// This mess can go away once https://github.com/rust-lang/rust/issues/76001 is stabilized
|
||||
quote! {
|
||||
impl crate::traits::NamedClass<crate::names::NameAsobo32> for #name {
|
||||
const NAME: crate::names::NameAsobo32 = crate::names::NameAsobo32::new(crate::crc::asobo32(#class_name.as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsobo32 = crate::names::NameAsobo32::new(crate::crc::asobo32(#class_name_legacy.as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameAsoboAlternate32> for #name {
|
||||
const NAME: crate::names::NameAsoboAlternate32 = crate::names::NameAsoboAlternate32::new(crate::crc::asobo_alternate32(#class_name.as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsoboAlternate32 = crate::names::NameAsoboAlternate32::new(crate::crc::asobo_alternate32(#class_name_legacy.as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameKalisto32> for #name {
|
||||
const NAME: crate::names::NameKalisto32 = crate::names::NameKalisto32::new(crate::crc::kalisto32(#class_name.as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameKalisto32 = crate::names::NameKalisto32::new(crate::crc::kalisto32(#class_name_legacy.as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameBlackSheep32> for #name {
|
||||
const NAME: crate::names::NameBlackSheep32 = crate::names::NameBlackSheep32::new(crate::crc::blacksheep32(#class_name.as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameBlackSheep32 = crate::names::NameBlackSheep32::new(crate::crc::blacksheep32(#class_name_legacy.as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameAsobo64> for #name {
|
||||
const NAME: crate::names::NameAsobo64 = crate::names::NameAsobo64::new(crate::crc::asobo64(#class_name.as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsobo64 = crate::names::NameAsobo64::new(crate::crc::asobo64(#class_name_legacy.as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<&'static str> for #name {
|
||||
const NAME: &'static str = #class_name;
|
||||
const NAME_LEGACY: &'static str = #class_name_legacy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ pub mod versions;
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use bff_derive::bigfiles;
|
||||
use petgraph::Graph;
|
||||
use serde::Serialize;
|
||||
|
||||
|
|
@ -36,6 +35,7 @@ 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;
|
||||
use crate::traits::{ReferencedNames, TryIntoVersionPlatform};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(AnimFrame {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod generic;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(AnimationGraph {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(AnimationGraphOverride {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(AreaLight {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod generic;
|
||||
mod v1_06_63_02_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
use v1_381_67_09_pc::CameraV1_381_67_09PC;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
use v1_06_63_02_pc::CameraZoneV1_06_63_02PC;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_291_03_06_pc;
|
||||
mod v1_381_67_09_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(CollisionVolData {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Conductor {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Decal {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(DialogEvent {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Entity {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Flare {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(FlareData {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(FogVolume {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(FxParticles {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(FxParticlesData {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_291_03_06_pc;
|
||||
mod v1_381_67_09_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
use v1_381_67_09_pc::GenWorldV1_381_67_09PC;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Graph {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
use v1_381_67_09_pc::GwRoadV1_381_67_09PC;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(HFog {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(HFogData {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(HullSplineZone {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod generic;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(LightProbeVolume {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(MassInstancingVolume {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(MaterialCollect {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod generic;
|
||||
pub mod v1_06_63_02_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(NetBingObj {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
// mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Occluder {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(OmniData {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Override {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Prefab {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(PrefabRef {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(ReflectionProbe {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
// mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Shader {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod v1_291_03_06_pc;
|
||||
pub mod v1_381_67_09_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(SkinData {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
pub mod generic;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(SoundEvent {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(SpecialEffectNode {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_381_67_09_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(SplineZone {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
// mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Terrain {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Texture {});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(Txt {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod generic;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(UserDefineScript {});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
use v1_06_63_02_pc::WarpV1_06_63_02PC;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_06_63_02_pc;
|
||||
mod v1_291_03_06_pc;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
mod v1_381_67_09_pc;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
use bff_derive::bff_class;
|
||||
use crate::macros::bff_class::bff_class;
|
||||
|
||||
bff_class!(XRefNode {});
|
||||
|
|
|
|||
228
bff/src/macros/bff_class.rs
Normal file
228
bff/src/macros/bff_class.rs
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
macro_rules! named_class {
|
||||
($class:ident) => {
|
||||
// This mess can go away once https://github.com/rust-lang/rust/issues/76001 is stabilized
|
||||
pastey::paste! {
|
||||
impl crate::traits::NamedClass<crate::names::NameAsobo32> for $class {
|
||||
const NAME: crate::names::NameAsobo32 = crate::names::NameAsobo32::new(crate::crc::asobo32(stringify!([<$class _Z>]).as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsobo32 = crate::names::NameAsobo32::new(crate::crc::asobo32(stringify!([<$class:upper>]).as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameAsoboAlternate32> for $class {
|
||||
const NAME: crate::names::NameAsoboAlternate32 = crate::names::NameAsoboAlternate32::new(crate::crc::asobo_alternate32(stringify!([<$class _Z>]).as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsoboAlternate32 = crate::names::NameAsoboAlternate32::new(crate::crc::asobo_alternate32(stringify!([<$class:upper>]).as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameKalisto32> for $class {
|
||||
const NAME: crate::names::NameKalisto32 = crate::names::NameKalisto32::new(crate::crc::kalisto32(stringify!([<$class _Z>]).as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameKalisto32 = crate::names::NameKalisto32::new(crate::crc::kalisto32(stringify!([<$class:upper>]).as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameBlackSheep32> for $class {
|
||||
const NAME: crate::names::NameBlackSheep32 = crate::names::NameBlackSheep32::new(crate::crc::blacksheep32(stringify!([<$class _Z>]).as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameBlackSheep32 = crate::names::NameBlackSheep32::new(crate::crc::blacksheep32(stringify!([<$class:upper>]).as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<crate::names::NameAsobo64> for $class {
|
||||
const NAME: crate::names::NameAsobo64 = crate::names::NameAsobo64::new(crate::crc::asobo64(stringify!([<$class _Z>]).as_bytes()));
|
||||
const NAME_LEGACY: crate::names::NameAsobo64 = crate::names::NameAsobo64::new(crate::crc::asobo64(stringify!([<$class:upper>]).as_bytes()));
|
||||
}
|
||||
|
||||
impl crate::traits::NamedClass<&'static str> for $class {
|
||||
const NAME: &'static str = stringify!([<$class _Z>]);
|
||||
const NAME_LEGACY: &'static str = stringify!([<$class:upper>]);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use named_class;
|
||||
|
||||
macro_rules! bff_class {
|
||||
($class:ident {}) => {
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, derive_more::From, derive_more::IsVariant, bff_derive::ReferencedNames)]
|
||||
pub enum $class {}
|
||||
|
||||
crate::macros::bff_class::named_class! { $class }
|
||||
|
||||
impl crate::traits::Export for $class {}
|
||||
impl crate::traits::Import for $class {}
|
||||
|
||||
impl crate::traits::TryFromVersionPlatform<&crate::bigfile::resource::Resource> for $class {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
fn try_from_version_platform(
|
||||
_object: &crate::bigfile::resource::Resource,
|
||||
_version: crate::bigfile::versions::Version,
|
||||
_platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<$class> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::TryFromVersionPlatform<&$class> for crate::bigfile::resource::Resource {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
fn try_from_version_platform(
|
||||
_class: &$class,
|
||||
_version: crate::bigfile::versions::Version,
|
||||
_platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pastey::paste! {
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct [<$class TryYourBestReport>] {
|
||||
pub total: usize,
|
||||
}
|
||||
|
||||
impl crate::traits::TryYourBest<&crate::bigfile::resource::Resource> for $class {
|
||||
type Report = [<$class TryYourBestReport>];
|
||||
fn update_report(_resource: &crate::bigfile::resource::Resource, _platform: crate::bigfile::platforms::Platform, report: &mut Self::Report) {
|
||||
report.total += 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for [<$class TryYourBestReport>] {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", stringify!($class))?;
|
||||
writeln!(f, "Total: {}", self.total)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
($class:ident { $($pattern:pat => $variant:ident),* $(,)? }) => {
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, derive_more::From, derive_more::IsVariant, bff_derive::ReferencedNames)]
|
||||
pub enum $class {
|
||||
$($variant(std::boxed::Box<$variant>)),*
|
||||
}
|
||||
|
||||
crate::macros::bff_class::named_class! { $class }
|
||||
|
||||
impl crate::traits::Export for $class {
|
||||
fn export(&self) -> crate::BffResult<std::collections::HashMap<std::ffi::OsString, crate::traits::Artifact>> {
|
||||
match self {
|
||||
$($class::$variant(class) => <$variant as crate::traits::Export>::export(class),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::Import for $class {
|
||||
fn import(&mut self, artifacts: &std::collections::HashMap<std::ffi::OsString, crate::traits::Artifact>) -> crate::BffResult<()> {
|
||||
match self {
|
||||
$($class::$variant(class) => <$variant as crate::traits::Import>::import(class, artifacts),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::TryFromVersionPlatform<&crate::bigfile::resource::Resource> for $class {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
fn try_from_version_platform(
|
||||
object: &crate::bigfile::resource::Resource,
|
||||
version: crate::bigfile::versions::Version,
|
||||
platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<$class> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
let shadow_class: $variant = <&crate::bigfile::resource::Resource as crate::traits::TryIntoVersionPlatform<$variant>>::try_into_version_platform(object, version, platform)?;
|
||||
Ok(std::boxed::Box::new(shadow_class).into())
|
||||
})*
|
||||
_ => Err(
|
||||
// TODO: Pick the right name based on the algorithm and suffix for the current BigFile
|
||||
crate::error::UnimplementedClassError::new(object.name, <Self as crate::traits::NamedClass<crate::names::NameAsobo32>>::NAME.into(), version, platform).into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::TryFromVersionPlatform<&$class> for crate::bigfile::resource::Resource {
|
||||
type Error = crate::error::Error;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
fn try_from_version_platform(
|
||||
class: &$class,
|
||||
version: crate::bigfile::versions::Version,
|
||||
platform: crate::bigfile::platforms::Platform,
|
||||
) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
match class {
|
||||
$($class::$variant(class) => {
|
||||
let object: crate::bigfile::resource::Resource = <&$variant as crate::traits::TryIntoVersionPlatform<crate::bigfile::resource::Resource>>::try_into_version_platform(class, version, platform)?;
|
||||
Ok(object)
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pastey::paste! {
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct [<$class TryYourBestReport>] {
|
||||
pub total: usize,
|
||||
$($variant: usize),*
|
||||
}
|
||||
|
||||
impl crate::traits::TryYourBest<&crate::bigfile::resource::Resource> for $class {
|
||||
type Report = [<$class TryYourBestReport>];
|
||||
fn update_report(resource: &crate::bigfile::resource::Resource, platform: crate::bigfile::platforms::Platform, report: &mut Self::Report) {
|
||||
report.total += 1;
|
||||
// TODO: Probably need a way to do this without specifying a version.
|
||||
$(
|
||||
report.$variant += <bool as Into<usize>>::into(<&crate::bigfile::resource::Resource as crate::traits::TryIntoVersionPlatform<$variant>>::try_into_version_platform(resource, crate::bigfile::versions::Version::Asobo(0, 0, 0, 0), platform).is_ok());
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for [<$class TryYourBestReport>] {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", stringify!($class))?;
|
||||
writeln!(f, "Total: {}", self.total)?;
|
||||
$(
|
||||
writeln!(f, "{}: {}", stringify!($variant), self.$variant)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
(#![generic] $class:ident {}) => {
|
||||
bff_class! {$class {}}
|
||||
|
||||
pastey::paste! {
|
||||
impl From<#class> for generic::[<$class Generic>] {
|
||||
fn from(
|
||||
class: $class,
|
||||
) -> generic::[<$class Generic>] {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
(#![generic] $class:ident { $($pattern:pat => $variant:ident),* $(,)? }) => {
|
||||
bff_class! {$class { $($pattern => $variant),* }}
|
||||
|
||||
pastey::paste! {
|
||||
impl From<$class> for generic::[<$class Generic>] {
|
||||
fn from(
|
||||
class: $class,
|
||||
) -> generic::[<$class Generic>] {
|
||||
match class {
|
||||
$($class::$variant(class) => {
|
||||
(*class).into()
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use bff_class;
|
||||
218
bff/src/macros/bigfiles.rs
Normal file
218
bff/src/macros/bigfiles.rs
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
macro_rules! bigfiles {
|
||||
($($pattern:pat => $bigfile:ident),* $(,)?) => {
|
||||
impl BigFile {
|
||||
#[allow(unused_imports)]
|
||||
pub fn read_platform<R: std::io::Read + std::io::Seek>(reader: &mut R, platform: crate::bigfile::platforms::Platform, version_override: &Option<crate::bigfile::versions::Version>) -> crate::BffResult<Self> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use binrw::BinRead;
|
||||
use crate::traits::BigFileIo;
|
||||
let _endian: crate::Endian = platform.into();
|
||||
let version: crate::bigfile::versions::Version = crate::helpers::FixedStringNull::<256>::read_be(reader)?.as_str().into();
|
||||
let version = version_override.clone().unwrap_or(version);
|
||||
match (&version, platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
<$bigfile as BigFileIo>::read(reader, version, platform)
|
||||
})*
|
||||
_ => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn write<W: std::io::Write + std::io::Seek>(&self, writer: &mut W, platform_override: Option<crate::bigfile::platforms::Platform>, version_override: &Option<crate::bigfile::versions::Version>, tag: Option<&str>) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use binrw::BinWrite;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = platform_override.unwrap_or(self.manifest.platform);
|
||||
let _endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
let version = version_override.as_ref().unwrap_or(version);
|
||||
let version_string = version.to_string();
|
||||
crate::helpers::FixedStringNull::<256>::write_be(&version_string.into(), writer)?;
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
<$bigfile as BigFileIo>::write(self, writer, tag)
|
||||
})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn dump_resource<W: std::io::Write + std::io::Seek>(&self, resource: &crate::bigfile::resource::Resource, writer: &mut W) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = self.manifest.platform;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::dump_resource(resource, writer, endian)?)})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_bff_resource<W: std::io::Write + std::io::Seek>(&self, resource: &crate::bigfile::resource::Resource, writer: &mut W) -> crate::BffResult<()> {
|
||||
let platform = self.manifest.platform;
|
||||
let version = &self.manifest.version;
|
||||
crate::bigfile::resource::Resource::dump_bff_resource(resource, writer, platform, version)
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn read_resource<R: std::io::Read + std::io::Seek>(&self, reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let platform = self.manifest.platform;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let version = &self.manifest.version;
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::read_resource(reader, endian)?)
|
||||
})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn read_bff_resource<R: std::io::Read + std::io::Seek>(&self, reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let crate::bigfile::resource::BffResourceHeader {
|
||||
platform,
|
||||
version,
|
||||
} = <crate::bigfile::resource::BffResourceHeader as binrw::BinRead>::read(reader)?;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::read_resource(reader, endian)?)
|
||||
})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
impl crate::bigfile::resource::Resource {
|
||||
pub fn dump_resource<W: std::io::Write + std::io::Seek>(&self, writer: &mut W, platform: crate::bigfile::platforms::Platform, version: &crate::bigfile::versions::Version) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let endian: crate::Endian = platform.into();
|
||||
let resource = self;
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::dump_resource(resource, writer, endian)?)})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
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) -> crate::BffResult<()> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
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.clone(), platform) {
|
||||
$($pattern => {crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::dump_resource(resource, writer, endian)?)})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn read_resource<R: std::io::Read + std::io::Seek>(reader: &mut R, platform: crate::bigfile::platforms::Platform, version: &crate::bigfile::versions::Version) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::read_resource(reader, endian)?)
|
||||
})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn read_bff_resource<R: std::io::Read + std::io::Seek>(reader: &mut R) -> crate::BffResult<crate::bigfile::resource::Resource> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
let crate::bigfile::resource::BffResourceHeader {
|
||||
platform,
|
||||
version,
|
||||
} = <crate::bigfile::resource::BffResourceHeader as binrw::BinRead>::read(reader)?;
|
||||
let endian: crate::Endian = platform.into();
|
||||
match (version.clone(), platform) {
|
||||
$($pattern => {
|
||||
crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
Ok(<$bigfile as BigFileIo>::ResourceType::read_resource(reader, endian)?)
|
||||
})*
|
||||
(version, platform) => Err(crate::error::UnimplementedVersionPlatformError::new(version, platform).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct BigFileTryYourBestReport {
|
||||
pub total: usize,
|
||||
$($bigfile: usize),*
|
||||
}
|
||||
|
||||
impl<R: std::io::Read + std::io::Seek> crate::traits::TryYourBest<&mut R> for BigFile {
|
||||
type Report = BigFileTryYourBestReport;
|
||||
fn update_report(reader: &mut R, platform: crate::bigfile::platforms::Platform, report: &mut Self::Report) {
|
||||
use crate::traits::BigFileIo;
|
||||
report.total += 1;
|
||||
// TODO: Probably need a way to do this without specifying a version.
|
||||
$(
|
||||
reader.seek(std::io::SeekFrom::Start(256)).unwrap();
|
||||
report.$bigfile += {crate::names::names().lock().unwrap().name_type = <$bigfile as BigFileIo>::NAME_TYPE;
|
||||
<bool as Into<usize>>::into(<$bigfile as BigFileIo>::read(reader, crate::bigfile::versions::Version::Asobo(0, 0, 0, 0), platform).is_ok())};
|
||||
)*
|
||||
reader.rewind().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BigFileTryYourBestReport {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "BigFile")?;
|
||||
writeln!(f, "Total: {}", self.total)?;
|
||||
$(
|
||||
writeln!(f, "{}: {}", stringify!($bigfile), self.$bigfile)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&crate::bigfile::versions::Version> for crate::names::NameType {
|
||||
type Error = crate::BffError;
|
||||
|
||||
fn try_from(version: &crate::bigfile::versions::Version) -> Result<crate::names::NameType, Self::Error> {
|
||||
use crate::bigfile::versions::Version::*;
|
||||
use crate::bigfile::platforms::Platform::*;
|
||||
use crate::traits::BigFileIo;
|
||||
match (version.clone(), PC) {
|
||||
$($pattern => Ok(<$bigfile as BigFileIo>::NAME_TYPE),)*
|
||||
(version, _platform) => Err(crate::error::UnimplementedVersionError::new(version).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) use bigfiles;
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
pub mod bff_class;
|
||||
pub mod bigfiles;
|
||||
pub mod classes;
|
||||
pub mod platforms;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue