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}