fugue_bytes/
order.rs

1use byteorder::ByteOrder;
2use std::cmp::Ordering;
3
4use crate::{BE, LE};
5use crate::endian::Endian;
6
7#[cfg(feature = "extra-integer-types")]
8use crate::primitives::*;
9
10pub trait Order: ByteOrder + Send + Sync + 'static {
11    const ENDIAN: Endian;
12    const NATIVE: bool;
13
14    fn read_i8(buf: &[u8]) -> i8 {
15        if buf.is_empty() {
16            0
17        } else {
18            buf[0] as i8
19        }
20    }
21
22    fn write_i8(buf: &mut [u8], n: i8) {
23        if !buf.is_empty() {
24            buf[0] = n as u8;
25        }
26    }
27
28    fn read_u8(buf: &[u8]) -> u8 {
29        if buf.is_empty() {
30            0
31        } else {
32            buf[0]
33        }
34    }
35
36    fn write_u8(buf: &mut [u8], n: u8) {
37        if !buf.is_empty() {
38            buf[0] = n;
39        }
40    }
41
42    #[cfg(feature = "extra-integer-types")]
43    fn read_u24(buf: &[u8]) -> u24;
44
45    #[cfg(feature = "extra-integer-types")]
46    fn write_u24(buf: &mut [u8], n: u24);
47
48    fn read_isize(buf: &[u8]) -> isize;
49    fn write_isize(buf: &mut [u8], n: isize);
50
51    fn read_usize(buf: &[u8]) -> usize;
52    fn write_usize(buf: &mut [u8], n: usize);
53
54    fn subpiece(destination: &mut [u8], source: &[u8], amount: usize);
55}
56
57impl Order for BE {
58    const ENDIAN: Endian = Endian::Big;
59    const NATIVE: bool = cfg!(target_endian = "big");
60
61
62    #[cfg(feature = "extra-integer-types")]
63    fn read_u24(buf: &[u8]) -> u24 {
64        let temp_u32 = u32::from_be_bytes([0, buf[0], buf[1], buf[2]]);
65        u24::new(temp_u32)
66    }
67
68    #[cfg(feature = "extra-integer-types")]
69    fn write_u24(buf: &mut [u8], n: u24) {
70        let temp = u32::from(n).to_be_bytes();
71        buf[0] = temp[1];
72        buf[1] = temp[2];
73        buf[2] = temp[3];
74    }
75
76    #[cfg(target_pointer_width = "32")]
77    fn read_isize(buf: &[u8]) -> isize {
78        Self::read_i32(buf) as isize
79    }
80
81    #[cfg(target_pointer_width = "64")]
82    fn read_isize(buf: &[u8]) -> isize {
83        Self::read_i64(buf) as isize
84    }
85
86    #[cfg(target_pointer_width = "32")]
87    fn write_isize(buf: &mut [u8], n: isize) {
88        Self::write_i32(buf, n as i32)
89    }
90
91    #[cfg(target_pointer_width = "64")]
92    fn write_isize(buf: &mut [u8], n: isize) {
93        Self::write_i64(buf, n as i64)
94    }
95
96    #[cfg(target_pointer_width = "32")]
97    fn read_usize(buf: &[u8]) -> usize {
98        Self::read_u32(buf) as usize
99    }
100
101    #[cfg(target_pointer_width = "64")]
102    fn read_usize(buf: &[u8]) -> usize {
103        Self::read_u64(buf) as usize
104    }
105
106    #[cfg(target_pointer_width = "32")]
107    fn write_usize(buf: &mut [u8], n: usize) {
108        Self::write_u32(buf, n as u32)
109    }
110
111    #[cfg(target_pointer_width = "64")]
112    fn write_usize(buf: &mut [u8], n: usize) {
113        Self::write_u64(buf, n as u64)
114    }
115
116    fn subpiece(destination: &mut [u8], source: &[u8], amount: usize) {
117        let amount = amount.min(source.len());
118        let trimmed = &source[..source.len() - amount];
119        match trimmed.len().cmp(&destination.len()) {
120            Ordering::Less => {
121                destination.copy_from_slice(&trimmed);
122                for i in destination[trimmed.len()..].iter_mut() {
123                    *i = 0;
124                }
125            }
126            Ordering::Equal => {
127                destination.copy_from_slice(&trimmed);
128            }
129            Ordering::Greater => destination.copy_from_slice(&trimmed[trimmed.len() - destination.len()..]),
130        }
131    }
132}
133
134impl Order for LE {
135    const ENDIAN: Endian = Endian::Little;
136    const NATIVE: bool = cfg!(target_endian = "little");
137
138    #[cfg(feature = "extra-integer-types")]
139    fn read_u24(buf: &[u8]) -> u24 {
140        let temp_u32 = u32::from_le_bytes([buf[0], buf[1], buf[2], 0]);
141        u24::new(temp_u32)
142    }
143
144    #[cfg(feature = "extra-integer-types")]
145    fn write_u24(buf: &mut [u8], n: u24) {
146        let temp = u32::from(n).to_le_bytes();
147        buf[0] = temp[0];
148        buf[1] = temp[1];
149        buf[2] = temp[2];
150    }
151
152    #[cfg(target_pointer_width = "32")]
153    fn read_isize(buf: &[u8]) -> isize {
154        Self::read_i32(buf) as isize
155    }
156
157    #[cfg(target_pointer_width = "64")]
158    fn read_isize(buf: &[u8]) -> isize {
159        Self::read_i64(buf) as isize
160    }
161
162    #[cfg(target_pointer_width = "32")]
163    fn write_isize(buf: &mut [u8], n: isize) {
164        Self::write_i32(buf, n as i32)
165    }
166
167    #[cfg(target_pointer_width = "64")]
168    fn write_isize(buf: &mut [u8], n: isize) {
169        Self::write_i64(buf, n as i64)
170    }
171
172    #[cfg(target_pointer_width = "32")]
173    fn read_usize(buf: &[u8]) -> usize {
174        Self::read_u32(buf) as usize
175    }
176
177    #[cfg(target_pointer_width = "64")]
178    fn read_usize(buf: &[u8]) -> usize {
179        Self::read_u64(buf) as usize
180    }
181
182    #[cfg(target_pointer_width = "32")]
183    fn write_usize(buf: &mut [u8], n: usize) {
184        Self::write_u32(buf, n as u32)
185    }
186
187    #[cfg(target_pointer_width = "64")]
188    fn write_usize(buf: &mut [u8], n: usize) {
189        Self::write_u64(buf, n as u64)
190    }
191
192    fn subpiece(destination: &mut [u8], source: &[u8], amount: usize) {
193        let amount = amount.min(source.len());
194        let trimmed = &source[amount..];
195        match trimmed.len().cmp(&destination.len()) {
196            Ordering::Less => {
197                destination[..trimmed.len()].copy_from_slice(&trimmed);
198                for i in destination[trimmed.len()..].iter_mut() {
199                    *i = 0;
200                }
201            }
202            Ordering::Equal | Ordering::Greater => {
203                destination.copy_from_slice(&trimmed[..destination.len()]);
204            }
205        }
206    }
207}