pwn/util/
packing.rs

1use crate::context::{
2    self,
3    Endianness::{Big, Little},
4};
5use crate::Bits;
6use byteorder::{BigEndian, ByteOrder, LittleEndian};
7
8/// Packs a `u8` to a 1-byte `Vec`.
9pub fn p8(v: u8) -> Vec<u8> {
10    vec![v]
11}
12
13/// Packs a `u16` to a 2-byte `Vec`.
14pub fn p16(v: u16) -> Vec<u8> {
15    let mut res: Vec<u8> = std::iter::repeat(0).take(2).collect();
16    match context::get_endianess() {
17        Big => BigEndian::write_u16(&mut res, v),
18        Little => LittleEndian::write_u16(&mut res, v),
19    };
20    res
21}
22
23/// Packs a `u32` to a 4-byte `Vec`.
24pub fn p32(v: u32) -> Vec<u8> {
25    let mut res: Vec<u8> = std::iter::repeat(0).take(4).collect();
26    match context::get_endianess() {
27        Big => BigEndian::write_u32(&mut res, v),
28        Little => LittleEndian::write_u32(&mut res, v),
29    };
30    res
31}
32
33/// Packs a `u64` to an 8-byte `Vec`.
34pub fn p64(v: u64) -> Vec<u8> {
35    let mut res: Vec<u8> = std::iter::repeat(0).take(8).collect();
36    match context::get_endianess() {
37        Big => BigEndian::write_u64(&mut res, v),
38        Little => LittleEndian::write_u64(&mut res, v),
39    };
40    res
41}
42
43/// Unpacks a 1 byte `Vec` to a `u8`.
44///
45/// # Panics
46///
47/// Panics when `v.len() < 1`.
48pub fn u8(v: &[u8]) -> u8 {
49    v[0]
50}
51
52/// Unpacks a 2 byte `Vec` to a `u16`.
53///
54/// # Panics
55///
56/// Panics when `v.len() < 2`.
57pub fn u16(v: &[u8]) -> u16 {
58    match context::get_endianess() {
59        Big => BigEndian::read_u16(v),
60        Little => LittleEndian::read_u16(v),
61    }
62}
63
64/// Unpacks a 4 byte `Vec` to a `u32`.
65///
66/// # Panics
67///
68/// Panics when `v.len() < 4`.
69pub fn u32(v: &[u8]) -> u32 {
70    match context::get_endianess() {
71        Big => BigEndian::read_u32(v),
72        Little => LittleEndian::read_u32(v),
73    }
74}
75
76/// Unpacks an 8 byte `Vec` to a `u64`.
77///
78/// # Panics
79///
80/// Panics when `v.len() < 8`.
81pub fn u64(v: &[u8]) -> u64 {
82    match context::get_endianess() {
83        Big => BigEndian::read_u64(v),
84        Little => LittleEndian::read_u64(v),
85    }
86}
87
88/// Automatically packs an integer in a [`context`] sensitive way.
89/// Returns `None` if the passed integer is too large to be casted down.
90pub fn pack<T>(v: T) -> Option<Vec<u8>>
91where
92    T: num_traits::ToPrimitive,
93{
94    match context::get_bits() {
95        Bits::Eight => Some(p8(v.to_u8()?)),
96        Bits::Sixteen => Some(p16(v.to_u16()?)),
97        Bits::ThirtyTwo => Some(p32(v.to_u32()?)),
98        Bits::SixtyFour => Some(p64(v.to_u64()?)),
99    }
100}
101
102/// Automatically unpacks a buffer to an integer in a [`context`] sensitive way.
103pub fn unpack(v: &[u8]) -> u64 {
104    match context::get_bits() {
105        Bits::Eight => u8(v) as u64,
106        Bits::Sixteen => u16(v) as u64,
107        Bits::ThirtyTwo => u32(v) as u64,
108        Bits::SixtyFour => u64(v),
109    }
110}