1#![warn(
2 missing_docs, unused,
3 trivial_numeric_casts,
4 future_incompatible,
5 rust_2018_compatibility,
6 rust_2018_idioms,
7 clippy::all
8)]
9
10#![doc(html_root_url = "https://docs.rs/lebe/0.5.0")]
11
12//! Dead simple endianness conversions.
13//! The following operations are implemented on
14//! `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `f32`, `f64`:
15//!
16//!
17//! ### Read Numbers
18//! ```rust
19//! use lebe::prelude::*;
20//! let mut reader: &[u8] = &[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
21//!
22//! let number : u64 = reader.read_from_little_endian()?;
23//! let number = u64::read_from_big_endian(&mut reader)?;
24//! # Ok::<(), std::io::Error>(())
25//! ```
26//!
27//! ### Read Slices
28//! ```rust
29//! use std::io::Read;
30//! use lebe::prelude::*;
31//! let mut reader: &[u8] = &[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
32//!
33//! let mut numbers: &mut [u64] = &mut [0, 0];
34//! reader.read_from_little_endian_into(numbers)?;
35//! # Ok::<(), std::io::Error>(())
36//! ```
37//!
38//! ### Write Numbers
39//! ```rust
40//! use std::io::Read;
41//! use lebe::prelude::*;
42//! let mut writer: Vec<u8> = Vec::new();
43//!
44//! let number: u64 = 1237691;
45//! writer.write_as_big_endian(&number)?;
46//! # Ok::<(), std::io::Error>(())
47//! ```
48//!
49//! ### Write Slices
50//! ```rust
51//! use std::io::Write;
52//! use lebe::prelude::*;
53//! let mut writer: Vec<u8> = Vec::new();
54//!
55//! let numbers: &[u64] = &[1_u64, 234545_u64];
56//! writer.write_as_little_endian(numbers)?;
57//! # Ok::<(), std::io::Error>(())
58//! ```
59//!
60
61
62/// Exports some of the most common types.
63pub mod prelude {
64 pub use super::Endian;
65 pub use super::io::{ WriteEndian, ReadEndian, ReadPrimitive };
66}
67
68/// Represents values that can swap their bytes to reverse their endianness.
69///
70/// Supports converting values in-place using [`swap_bytes`] or [`convert_current_to_little_endian`]:
71/// Supports converting while transferring ownership using
72/// [`from_little_endian_into_current`] or [`from_current_into_little_endian`].
73///
74///
75/// For the types `u8`, `i8`, `&[u8]` and `&[i8]`, this trait will never transform any data,
76/// as they are just implemented for completeness.
77pub trait Endian {
78
79 /// Swaps all bytes in this value, inverting its endianness.
80 fn swap_bytes(&mut self);
81
82 /// On a little endian machine, this does nothing.
83 /// On a big endian machine, the bytes of this value are reversed.
84 #[inline] fn convert_current_to_little_endian(&mut self) {
85 #[cfg(target_endian = "big")] {
86 self.swap_bytes();
87 }
88 }
89
90 /// On a big endian machine, this does nothing.
91 /// On a little endian machine, the bytes of this value are reversed.
92 #[inline] fn convert_current_to_big_endian(&mut self) {
93 #[cfg(target_endian = "little")] {
94 self.swap_bytes();
95 }
96 }
97
98 /// On a little endian machine, this does nothing.
99 /// On a big endian machine, the bytes of this value are reversed.
100 #[inline] fn convert_little_endian_to_current(&mut self) {
101 #[cfg(target_endian = "big")] {
102 self.swap_bytes();
103 }
104 }
105
106 /// On a big endian machine, this does nothing.
107 /// On a little endian machine, the bytes of this value are reversed.
108 #[inline] fn convert_big_endian_to_current(&mut self) {
109 #[cfg(target_endian = "little")] {
110 self.swap_bytes();
111 }
112 }
113
114 /// On a little endian machine, this does nothing.
115 /// On a big endian machine, the bytes of this value are reversed.
116 #[inline] fn from_current_into_little_endian(mut self) -> Self where Self: Sized {
117 self.convert_current_to_little_endian();
118 self
119 }
120
121 /// On a big endian machine, this does nothing.
122 /// On a little endian machine, the bytes of this value are reversed.
123 #[inline] fn from_current_into_big_endian(mut self) -> Self where Self: Sized {
124 self.convert_current_to_big_endian();
125 self
126 }
127
128 /// On a little endian machine, this does nothing.
129 /// On a big endian machine, the bytes of this value are reversed.
130 #[inline] fn from_little_endian_into_current(mut self) -> Self where Self: Sized {
131 self.convert_little_endian_to_current();
132 self
133 }
134
135 /// On a big endian machine, this does nothing.
136 /// On a little endian machine, the bytes of this value are reversed.
137 #[inline] fn from_big_endian_into_current(mut self) -> Self where Self: Sized {
138 self.convert_big_endian_to_current();
139 self
140 }
141}
142
143
144// call a macro for each argument
145macro_rules! call_single_arg_macro_for_each {
146 ($macro: ident, $( $arguments: ident ),* ) => {
147 $( $macro! { $arguments } )*
148 };
149}
150
151// implement this interface for primitive signed and unsigned integers
152macro_rules! implement_simple_primitive_endian {
153 ($type: ident) => {
154 impl Endian for $type {
155 fn swap_bytes(&mut self) {
156 *self = $type::swap_bytes(*self);
157 }
158 }
159 };
160}
161
162
163call_single_arg_macro_for_each! {
164 implement_simple_primitive_endian,
165 u16, u32, u64, u128, i16, i32, i64, i128
166}
167
168// no-op implementations
169impl Endian for u8 { fn swap_bytes(&mut self) {} }
170impl Endian for i8 { fn swap_bytes(&mut self) {} }
171impl Endian for [u8] { fn swap_bytes(&mut self) {} }
172impl Endian for [i8] { fn swap_bytes(&mut self) {} }
173
174// implement this interface for primitive floats, because they do not have a `swap_bytes()` in `std`
175macro_rules! implement_float_primitive_by_bits {
176 ($type: ident) => {
177 impl Endian for $type {
178 fn swap_bytes(&mut self) {
179 *self = Self::from_bits(self.to_bits().swap_bytes());
180 }
181 }
182 };
183}
184
185
186implement_float_primitive_by_bits!(f32);
187implement_float_primitive_by_bits!(f64);
188
189macro_rules! implement_slice_by_element {
190 ($type: ident) => {
191 impl Endian for [$type] {
192 fn swap_bytes(&mut self) {
193 for number in self.iter_mut() { // TODO SIMD?
194 number.swap_bytes();
195 }
196 }
197 }
198 };
199}
200
201call_single_arg_macro_for_each! {
202 implement_slice_by_element,
203 u16, u32, u64, u128,
204 i16, i32, i64, i128,
205 f64, f32
206}
207
208/// Easily write primitives and slices of primitives to
209/// binary `std::io::Write` streams and easily read from binary `std::io::Read` streams.
210///
211/// Also contains the unsafe `bytes` module for reinterpreting values as byte slices and vice versa.
212pub mod io {
213 use super::Endian;
214 use std::io::{Read, Write, Result};
215
216 /// Reinterpret values as byte slices and byte slices as values unsafely.
217 pub mod bytes {
218 use std::io::{Read, Write, Result};
219
220 /// View this slice of values as a slice of bytes.
221 #[inline]
222 pub unsafe fn slice_as_bytes<T>(value: &[T]) -> &[u8] {
223 std::slice::from_raw_parts(
224 value.as_ptr() as *const u8,
225 value.len() * std::mem::size_of::<T>()
226 )
227 }
228
229 /// View this slice of values as a mutable slice of bytes.
230 #[inline]
231 pub unsafe fn slice_as_bytes_mut<T>(value: &mut [T]) -> &mut [u8] {
232 std::slice::from_raw_parts_mut(
233 value.as_mut_ptr() as *mut u8,
234 value.len() * std::mem::size_of::<T>()
235 )
236 }
237
238 /// View this reference as a slice of bytes.
239 #[inline]
240 pub unsafe fn value_as_bytes<T: Sized>(value: &T) -> &[u8] {
241 std::slice::from_raw_parts(
242 value as *const T as *const u8,
243 std::mem::size_of::<T>()
244 )
245 }
246
247 /// View this reference as a mutable slice of bytes.
248 #[inline]
249 pub unsafe fn value_as_bytes_mut<T: Sized>(value: &mut T) ->&mut [u8] {
250 std::slice::from_raw_parts_mut(
251 value as *mut T as *mut u8,
252 std::mem::size_of::<T>()
253 )
254 }
255
256 /// View this slice as a mutable slice of bytes and write it.
257 #[inline]
258 pub unsafe fn write_slice<T>(write: &mut impl Write, value: &[T]) -> Result<()> {
259 write.write_all(slice_as_bytes(value))
260 }
261
262 /// Read a slice of bytes into the specified slice.
263 #[inline]
264 pub unsafe fn read_slice<T>(read: &mut impl Read, value: &mut [T]) -> Result<()> {
265 read.read_exact(slice_as_bytes_mut(value))
266 }
267
268 /// View this reference as a mutable slice of bytes and write it.
269 #[inline]
270 pub unsafe fn write_value<T: Sized>(write: &mut impl Write, value: &T) -> Result<()> {
271 write.write_all(value_as_bytes(value))
272 }
273
274 /// Read a slice of bytes into the specified reference.
275 #[inline]
276 pub unsafe fn read_value<T: Sized>(read: &mut impl Read, value: &mut T) -> Result<()> {
277 read.read_exact(value_as_bytes_mut(value))
278 }
279 }
280
281 /// A `std::io::Write` output stream which supports writing any primitive values as bytes.
282 /// Will encode the values to be either little endian or big endian, as desired.
283 ///
284 /// This extension trait is implemented for all `Write` types.
285 /// Add `use lebe::io::WriteEndian;` to your code
286 /// to automatically unlock this functionality for all types that implement `Write`.
287 pub trait WriteEndian<T: ?Sized> {
288
289 /// Write the byte value of the specified reference, converting it to little endianness
290 fn write_as_little_endian(&mut self, value: &T) -> Result<()>;
291
292 /// Write the byte value of the specified reference, converting it to big endianness
293 fn write_as_big_endian(&mut self, value: &T) -> Result<()>;
294
295 /// Write the byte value of the specified reference, not converting it
296 fn write_as_native_endian(&mut self, value: &T) -> Result<()> {
297 #[cfg(target_endian = "little")] { self.write_as_little_endian(value) }
298 #[cfg(target_endian = "big")] { self.write_as_big_endian(value) }
299 }
300 }
301
302 /// A `std::io::Read` input stream which supports reading any primitive values from bytes.
303 /// Will decode the values from either little endian or big endian, as desired.
304 ///
305 /// This extension trait is implemented for all `Read` types.
306 /// Add `use lebe::io::ReadEndian;` to your code
307 /// to automatically unlock this functionality for all types that implement `Read`.
308 pub trait ReadEndian<T: ?Sized> {
309
310 /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.
311 fn read_from_little_endian_into(&mut self, value: &mut T) -> Result<()>;
312
313 /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.
314 fn read_from_big_endian_into(&mut self, value: &mut T) -> Result<()>;
315
316 /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.
317 fn read_from_native_endian_into(&mut self, value: &mut T) -> Result<()> {
318 #[cfg(target_endian = "little")] { self.read_from_little_endian_into(value) }
319 #[cfg(target_endian = "big")] { self.read_from_big_endian_into(value) }
320 }
321
322 /// Read the byte value of the inferred type
323 #[inline]
324 fn read_from_little_endian(&mut self) -> Result<T> where T: Sized + Default {
325 let mut value = T::default();
326 self.read_from_little_endian_into(&mut value)?;
327 Ok(value)
328 }
329
330 /// Read the byte value of the inferred type
331 #[inline]
332 fn read_from_big_endian(&mut self) -> Result<T> where T: Sized + Default {
333 let mut value = T::default();
334 self.read_from_big_endian_into(&mut value)?;
335 Ok(value)
336 }
337
338 /// Read the byte value of the inferred type
339 #[inline]
340 fn read_from_native_endian(&mut self) -> Result<T> where T: Sized + Default {
341 #[cfg(target_endian = "little")] { self.read_from_little_endian() }
342 #[cfg(target_endian = "big")] { self.read_from_big_endian() }
343 }
344 }
345
346 // implement primitive for all types that are implemented by `Read`
347 impl<R: Read + ReadEndian<P>, P: Default> ReadPrimitive<R> for P {}
348
349
350 /// Offers a prettier versions of reading a primitive number.
351 ///
352 /// The default way of reading a value is:
353 /// ```rust
354 /// # use std::io::Read;
355 /// # use lebe::prelude::*;
356 /// # let mut reader : &[u8] = &[2, 1];
357 ///
358 /// let number: u16 = reader.read_from_little_endian()?;
359 /// println!("{}", number);
360 /// # Ok::<(), std::io::Error>(())
361 ///
362 /// ```
363 ///
364 /// This trait enables you to use expressions:
365 /// ```rust
366 /// # use std::io::Read;
367 /// # use lebe::prelude::*;
368 /// # let mut reader : &[u8] = &[2, 1];
369 ///
370 /// println!("{}", u16::read_from_little_endian(&mut reader)?);
371 /// # Ok::<(), std::io::Error>(())
372 /// ```
373 /// .
374 ///
375 pub trait ReadPrimitive<R: Read + ReadEndian<Self>> : Sized + Default {
376 /// Read this value from the supplied reader. Same as `ReadEndian::read_from_little_endian()`.
377 fn read_from_little_endian(read: &mut R) -> Result<Self> {
378 read.read_from_little_endian()
379 }
380
381 /// Read this value from the supplied reader. Same as `ReadEndian::read_from_big_endian()`.
382 fn read_from_big_endian(read: &mut R) -> Result<Self> {
383 read.read_from_big_endian()
384 }
385
386 /// Read this value from the supplied reader. Same as `ReadEndian::read_from_native_endian()`.
387 fn read_from_native_endian(read: &mut R) -> Result<Self> {
388 read.read_from_native_endian()
389 }
390 }
391
392 macro_rules! implement_simple_primitive_write {
393 ($type: ident) => {
394 impl<W: Write> WriteEndian<$type> for W {
395 fn write_as_little_endian(&mut self, value: &$type) -> Result<()> {
396 unsafe { bytes::write_value(self, &value.from_current_into_little_endian()) }
397 }
398
399 fn write_as_big_endian(&mut self, value: &$type) -> Result<()> {
400 unsafe { bytes::write_value(self, &value.from_current_into_big_endian()) }
401 }
402 }
403
404 impl<R: Read> ReadEndian<$type> for R {
405 #[inline]
406 fn read_from_little_endian_into(&mut self, value: &mut $type) -> Result<()> {
407 unsafe { bytes::read_value(self, value)?; }
408 value.convert_little_endian_to_current();
409 Ok(())
410 }
411
412 #[inline]
413 fn read_from_big_endian_into(&mut self, value: &mut $type) -> Result<()> {
414 unsafe { bytes::read_value(self, value)?; }
415 value.convert_big_endian_to_current();
416 Ok(())
417 }
418 }
419 };
420 }
421
422 call_single_arg_macro_for_each! {
423 implement_simple_primitive_write,
424 u8, u16, u32, u64, u128,
425 i8, i16, i32, i64, i128,
426 f32, f64
427 }
428
429
430 macro_rules! implement_slice_io {
431 ($type: ident) => {
432 impl<W: Write> WriteEndian<[$type]> for W {
433 fn write_as_little_endian(&mut self, value: &[$type]) -> Result<()> {
434 #[cfg(target_endian = "big")] {
435 for number in value { // TODO SIMD!
436 self.write_as_little_endian(number)?;
437 }
438 }
439
440 // else write whole slice
441 #[cfg(target_endian = "little")]
442 unsafe { bytes::write_slice(self, value)?; }
443
444 Ok(())
445 }
446
447 fn write_as_big_endian(&mut self, value: &[$type]) -> Result<()> {
448 #[cfg(target_endian = "little")] {
449 for number in value { // TODO SIMD!
450 self.write_as_big_endian(number)?;
451 }
452 }
453
454 // else write whole slice
455 #[cfg(target_endian = "big")]
456 unsafe { bytes::write_slice(self, value)?; }
457
458 Ok(())
459 }
460 }
461
462 impl<R: Read> ReadEndian<[$type]> for R {
463 fn read_from_little_endian_into(&mut self, value: &mut [$type]) -> Result<()> {
464 unsafe { bytes::read_slice(self, value)? };
465 value.convert_little_endian_to_current();
466 Ok(())
467 }
468
469 fn read_from_big_endian_into(&mut self, value: &mut [$type]) -> Result<()> {
470 unsafe { bytes::read_slice(self, value)? };
471 value.convert_big_endian_to_current();
472 Ok(())
473 }
474 }
475 };
476 }
477
478 call_single_arg_macro_for_each! {
479 implement_slice_io,
480 u8, u16, u32, u64, u128,
481 i8, i16, i32, i64, i128,
482 f64, f32
483 }
484
485
486
487 // TODO: SIMD
488 /*impl<R: Read> ReadEndian<[f32]> for R {
489 fn read_from_little_endian_into(&mut self, value: &mut [f32]) -> Result<()> {
490 unsafe { bytes::read_slice(self, value)? };
491 value.convert_little_endian_to_current();
492 Ok(())
493 }
494
495 fn read_from_big_endian_into(&mut self, value: &mut [f32]) -> Result<()> {
496 unsafe { bytes::read_slice(self, value)? };
497 value.convert_big_endian_to_current();
498 Ok(())
499 }
500 }
501
502 impl<W: Write> WriteEndian<[f32]> for W {
503 fn write_as_big_endian(&mut self, value: &[f32]) -> Result<()> {
504 if cfg!(target_endian = "little") {
505
506 // FIX ME this SIMD optimization makes no difference ... why? like, ZERO difference, not even worse
507// #[cfg(feature = "simd")]
508 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
509 unsafe {
510 if is_x86_feature_detected!("avx2") {
511 write_bytes_avx(self, value);
512 return Ok(());
513 }
514 }
515
516 // otherwise (no avx2 available)
517// for number in value {
518// self.write_as_little_endian(number);
519// }
520//
521// return Ok(());
522 unimplemented!();
523
524 #[target_feature(enable = "avx2")]
525 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
526 unsafe fn write_bytes_avx(write: &mut impl Write, slice: &[f32]) -> Result<()> {
527 #[cfg(target_arch = "x86")] use std::arch::x86 as mm;
528 #[cfg(target_arch = "x86_64")] use std::arch::x86_64 as mm;
529
530 let bytes: &[u8] = crate::io::bytes::slice_as_bytes(slice);
531 let mut chunks = bytes.chunks_exact(32);
532
533 let indices = mm::_mm256_set_epi8(
534 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
535 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
536// 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12,
537// 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12
538 );
539
540 for chunk in &mut chunks {
541 let data = mm::_mm256_loadu_si256(chunk.as_ptr() as _);
542 let result = mm::_mm256_shuffle_epi8(data, indices);
543 let mut out = [0_u8; 32];
544 mm::_mm256_storeu_si256(out.as_mut_ptr() as _, result);
545 write.write_all(&out)?;
546 }
547
548 let remainder = chunks.remainder();
549
550 { // copy remainder into larger slice, with zeroes at the end
551 let mut last_chunk = [0_u8; 32];
552 last_chunk[0..remainder.len()].copy_from_slice(remainder);
553 let data = mm::_mm256_loadu_si256(last_chunk.as_ptr() as _);
554 let result = mm::_mm256_shuffle_epi8(data, indices);
555 mm::_mm256_storeu_si256(last_chunk.as_mut_ptr() as _, result);
556 write.write_all(&last_chunk[0..remainder.len()])?;
557 }
558
559 Ok(())
560 }
561 }
562
563 else {
564 unsafe { bytes::write_slice(self, value)?; }
565 Ok(())
566 }
567 }
568
569 fn write_as_little_endian(&mut self, value: &[f32]) -> Result<()> {
570 for number in value {
571 self.write_as_little_endian(number)?;
572 }
573
574 Ok(())
575 }
576 }*/
577}
578
579