physis/
common_file_operations.rs1use binrw::{BinReaderExt, BinResult, binread};
5use half::f16;
6use std::ffi::CString;
7use std::io::SeekFrom;
8
9pub(crate) fn read_bool_from<T: std::convert::From<u8> + std::cmp::PartialEq>(x: T) -> bool {
10 x == T::from(1u8)
11}
12
13pub(crate) fn write_bool_as<T: std::convert::From<u8>>(x: &bool) -> T {
14 if *x { T::from(1u8) } else { T::from(0u8) }
15}
16
17pub(crate) fn read_string(byte_stream: Vec<u8>) -> String {
18 let str = String::from_utf8(byte_stream).unwrap();
19 str.trim_matches(char::from(0)).to_string() }
21
22pub(crate) fn write_string(str: &String) -> Vec<u8> {
23 let c_string = CString::new(&**str).unwrap();
24 c_string.as_bytes_with_nul().to_vec()
25}
26
27pub(crate) fn get_string_len(str: &String) -> usize {
28 let c_string = CString::new(&**str).unwrap();
29 c_string.count_bytes() + 1 }
31
32#[binrw::parser(reader)]
33pub(crate) fn strings_parser(
34 base_offset: u64,
35 strings_offset: &Vec<u16>,
36) -> BinResult<Vec<String>> {
37 let mut strings: Vec<String> = vec![];
38
39 for offset in strings_offset {
40 let string_offset = base_offset + *offset as u64;
41
42 let mut string = String::new();
43
44 reader.seek(SeekFrom::Start(string_offset))?;
45 let mut next_char = reader.read_le::<u8>().unwrap() as char;
46 while next_char != '\0' {
47 string.push(next_char);
48 next_char = reader.read_le::<u8>().unwrap() as char;
49 }
50
51 strings.push(string);
52 }
53
54 Ok(strings)
55}
56
57fn read_half1(data: [u16; 1]) -> Half1 {
58 Half1 {
59 value: f16::from_bits(data[0]),
60 }
61}
62
63#[binread]
64#[derive(Debug, Default, Clone, Copy)]
65#[br(map = read_half1)]
66pub(crate) struct Half1 {
67 pub value: f16,
68}
69
70fn read_half2(data: [u16; 2]) -> Half2 {
71 Half2 {
72 x: f16::from_bits(data[0]),
73 y: f16::from_bits(data[0]),
74 }
75}
76
77#[binread]
78#[derive(Debug, Default, Clone, Copy)]
79#[br(map = read_half2)]
80pub(crate) struct Half2 {
81 pub x: f16,
82 pub y: f16,
83}
84
85fn read_half3(data: [u16; 3]) -> Half3 {
86 Half3 {
87 r: f16::from_bits(data[0]),
88 g: f16::from_bits(data[0]),
89 b: f16::from_bits(data[0]),
90 }
91}
92
93#[binread]
94#[derive(Debug, Default, Clone, Copy)]
95#[br(map = read_half3)]
96pub(crate) struct Half3 {
97 pub r: f16,
98 pub g: f16,
99 pub b: f16,
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 const DATA: [u8; 2] = [0u8, 1u8];
107
108 #[test]
111 fn read_bool_u8() {
112 assert!(!read_bool_from::<u8>(DATA[0]));
113 assert!(read_bool_from::<u8>(DATA[1]));
114 }
115
116 #[test]
117 fn write_bool_u8() {
118 assert_eq!(write_bool_as::<u8>(&false), DATA[0]);
119 assert_eq!(write_bool_as::<u8>(&true), DATA[1]);
120 }
121
122 const STRING_DATA: [u8; 4] = [0x46u8, 0x4Fu8, 0x4Fu8, 0x0u8];
124
125 #[test]
126 fn read_string() {
127 assert_eq!(
129 crate::common_file_operations::read_string(STRING_DATA.to_vec()),
130 "FOO".to_string()
131 );
132 }
133
134 #[test]
135 fn write_string() {
136 assert_eq!(
138 crate::common_file_operations::write_string(&"FOO".to_string()),
139 STRING_DATA.to_vec()
140 );
141 }
142
143 #[test]
144 fn get_string_len() {
145 assert_eq!(
147 crate::common_file_operations::get_string_len(&"FOO".to_string()),
148 4
149 );
150 }
151}