1use alloc::{format, vec::Vec};
2use core::fmt;
3
4use anyhow::{Result, ensure};
5use num_traits::PrimInt;
6use object::{Endian, Object};
7
8pub struct ReallySigned<N: PrimInt>(pub N);
10
11impl<N: PrimInt> fmt::LowerHex for ReallySigned<N> {
12 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13 let num = self.0.to_i64().unwrap();
14 let prefix = if f.alternate() { "0x" } else { "" };
15 let bare_hex = format!("{:x}", num.abs());
16 f.pad_integral(num >= 0, prefix, &bare_hex)
17 }
18}
19
20impl<N: PrimInt> fmt::UpperHex for ReallySigned<N> {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 let num = self.0.to_i64().unwrap();
23 let prefix = if f.alternate() { "0x" } else { "" };
24 let bare_hex = format!("{:X}", num.abs());
25 f.pad_integral(num >= 0, prefix, &bare_hex)
26 }
27}
28
29pub fn read_u32(obj_file: &object::File, reader: &mut &[u8]) -> Result<u32> {
30 ensure!(reader.len() >= 4, "Not enough bytes to read u32");
31 let value = reader[..4].try_into()?;
32 *reader = &reader[4..];
33 Ok(obj_file.endianness().read_u32(value))
34}
35
36pub fn read_u16(obj_file: &object::File, reader: &mut &[u8]) -> Result<u16> {
37 ensure!(reader.len() >= 2, "Not enough bytes to read u16");
38 let value = reader[..2].try_into()?;
39 *reader = &reader[2..];
40 Ok(obj_file.endianness().read_u16(value))
41}
42
43pub fn read_u8(reader: &mut &[u8]) -> Result<u8> {
44 ensure!(!reader.is_empty(), "Not enough bytes to read u8");
45 let value = reader[0];
46 *reader = &reader[1..];
47 Ok(value)
48}
49
50pub fn align_size_to_4(size: usize) -> usize { (size + 3) & !3 }
51
52#[cfg(feature = "std")]
53pub fn align_data_to_4<W: std::io::Write + ?Sized>(
54 writer: &mut W,
55 len: usize,
56) -> std::io::Result<()> {
57 const ALIGN_BYTES: &[u8] = &[0; 4];
58 if !len.is_multiple_of(4) {
59 writer.write_all(&ALIGN_BYTES[..4 - len % 4])?;
60 }
61 Ok(())
62}
63
64pub fn align_u64_to(len: u64, align: u64) -> u64 { len + ((align - (len % align)) % align) }
65
66pub fn align_data_slice_to(data: &mut Vec<u8>, align: u64) {
67 data.resize(align_u64_to(data.len() as u64, align) as usize, 0);
68}
69
70#[derive(Copy, Clone, Debug)]
73pub struct RawFloat(pub f32);
74impl PartialEq for RawFloat {
75 fn eq(&self, other: &Self) -> bool { self.0.to_bits() == other.0.to_bits() }
76}
77impl Eq for RawFloat {}
78impl Ord for RawFloat {
79 fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.0.to_bits().cmp(&other.0.to_bits()) }
80}
81impl PartialOrd for RawFloat {
82 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { Some(self.cmp(other)) }
83}
84
85#[derive(Copy, Clone, Debug)]
88pub struct RawDouble(pub f64);
89impl PartialEq for RawDouble {
90 fn eq(&self, other: &Self) -> bool { self.0.to_bits() == other.0.to_bits() }
91}
92impl Eq for RawDouble {}
93impl Ord for RawDouble {
94 fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.0.to_bits().cmp(&other.0.to_bits()) }
95}
96impl PartialOrd for RawDouble {
97 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { Some(self.cmp(other)) }
98}