serde_hkx_features/convert/
hkx_checker.rs1use std::path::{Path, PathBuf};
3
4use crate::Format;
5
6pub fn detect_hkx_format(input_path: &Path) -> Result<Format, Error> {
12 let header = {
13 let mut header = [0_u8; 17];
14 let mut file = std::fs::File::open(input_path).map_err(|source| Error::FailedReadFile {
15 source,
16 path: input_path.to_path_buf(),
17 })?;
18 std::io::Read::read_exact(&mut file, &mut header).map_err(|source| {
19 Error::FailedReadFile {
20 source,
21 path: input_path.to_path_buf(),
22 }
23 })?;
24 header
25 };
26
27 let is_tag_file = {
31 const EXPECTED_MAGIC: [u8; 8] = [
33 0x1E, 0x0D, 0xB0, 0xCA, 0xCE, 0xFA, 0x11, 0xD0, ];
36 header[0..8] == EXPECTED_MAGIC
37 };
38 if is_tag_file {
39 return Err(Error::UnsupportedTagFile {
40 path: input_path.to_path_buf(),
41 });
42 }
43
44 let is_hkx = {
45 const EXPECTED_MAGIC: [u8; 8] = [
47 0x57, 0xE0, 0xE0, 0x57, 0x10, 0xC0, 0xC0, 0x10, ];
50 header[0..8] == EXPECTED_MAGIC
51 };
52 if !is_hkx {
53 return Err(Error::HkxInvalidMagic {
54 input_path: input_path.to_path_buf(),
55 magic_bytes: header,
56 });
57 }
58
59 let ptr_size = header[16];
61 let current_format = match ptr_size {
62 4 => Format::Win32,
63 8 => Format::Amd64,
64 _ => {
65 return Err(Error::HkxInvalidHeader {
66 input_path: input_path.to_path_buf(),
67 actual: ptr_size,
68 });
69 }
70 };
71
72 Ok(current_format)
73}
74
75#[allow(clippy::enum_variant_names)]
76#[derive(Debug, snafu::Snafu)]
77#[snafu(visibility(pub))]
78pub enum Error {
79 #[snafu(display("serde-hkx does not currently support tag files. path: {}", path.display()))]
80 UnsupportedTagFile { path: PathBuf },
81
82 #[snafu(display("Failed to read this path: {}", path.display()))]
84 FailedReadFile {
85 source: std::io::Error,
86 path: PathBuf,
87 },
88
89 #[snafu(display(
90 "HKX file {} did not have the expected Havok magic numbers. \
91 Expected magic=[0x57, 0xe0, 0xe0, 0x57, 0x10, 0xc0, 0xc0, 0x10, ...], \
92 but got {magic_bytes:x?}. \
93 This file is not a valid Havok animation or may be from an unsupported version.",
94 input_path.display()
95 ))]
96 HkxInvalidMagic {
97 input_path: PathBuf,
98 magic_bytes: [u8; 17],
99 },
100
101 #[snafu(display(
102 "HKX pointer size check failed for {}. \
103 Expected pointer size 4/8-byte, but could not determine a valid header or got {actual}-byte. \
104 The HKX may be malformed or from an incompatible platform.",
105 input_path.display()
106 ))]
107 HkxInvalidHeader { input_path: PathBuf, actual: u8 },
108}