physis/
common_file_operations.rs
1use 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
57#[binrw::parser(reader)]
58pub(crate) fn read_string_until_null() -> BinResult<String> {
59 let mut string = String::new();
60
61 let mut next_char = reader.read_le::<u8>().unwrap() as char;
62 while next_char != '\0' {
63 string.push(next_char);
64 next_char = reader.read_le::<u8>().unwrap() as char;
65 }
66 Ok(string)
67}
68
69fn read_half1(data: [u16; 1]) -> Half1 {
70 Half1 {
71 value: f16::from_bits(data[0]),
72 }
73}
74
75#[binread]
76#[derive(Debug, Default, Clone, Copy)]
77#[br(map = read_half1)]
78pub(crate) struct Half1 {
79 pub value: f16,
80}
81
82fn read_half2(data: [u16; 2]) -> Half2 {
83 Half2 {
84 x: f16::from_bits(data[0]),
85 y: f16::from_bits(data[1]),
86 }
87}
88
89#[binread]
90#[derive(Debug, Default, Clone, Copy)]
91#[br(map = read_half2)]
92pub(crate) struct Half2 {
93 pub x: f16,
94 pub y: f16,
95}
96
97fn read_half3(data: [u16; 3]) -> Half3 {
98 Half3 {
99 r: f16::from_bits(data[0]),
100 g: f16::from_bits(data[1]),
101 b: f16::from_bits(data[2]),
102 }
103}
104
105#[binread]
106#[derive(Debug, Default, Clone, Copy)]
107#[br(map = read_half3)]
108pub(crate) struct Half3 {
109 pub r: f16,
110 pub g: f16,
111 pub b: f16,
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 const DATA: [u8; 2] = [0u8, 1u8];
119
120 #[test]
123 fn read_bool_u8() {
124 assert!(!read_bool_from::<u8>(DATA[0]));
125 assert!(read_bool_from::<u8>(DATA[1]));
126 }
127
128 #[test]
129 fn write_bool_u8() {
130 assert_eq!(write_bool_as::<u8>(&false), DATA[0]);
131 assert_eq!(write_bool_as::<u8>(&true), DATA[1]);
132 }
133
134 const STRING_DATA: [u8; 4] = [0x46u8, 0x4Fu8, 0x4Fu8, 0x0u8];
136
137 #[test]
138 fn read_string() {
139 assert_eq!(
141 crate::common_file_operations::read_string(STRING_DATA.to_vec()),
142 "FOO".to_string()
143 );
144 }
145
146 #[test]
147 fn write_string() {
148 assert_eq!(
150 crate::common_file_operations::write_string(&"FOO".to_string()),
151 STRING_DATA.to_vec()
152 );
153 }
154
155 #[test]
156 fn get_string_len() {
157 assert_eq!(
159 crate::common_file_operations::get_string_len(&"FOO".to_string()),
160 4
161 );
162 }
163}