byteordered/base.rs
1//! Base Endianness type module.
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian, ReadBytesExt, WriteBytesExt};
4use std::default::Default;
5use std::io::{Read, Result as IoResult, Write};
6use std::marker::PhantomData;
7
8/// Trait for any type which has an opposite type. This is used to convert
9/// immaterial types representing "little endian" into "big endian" and vice
10/// versa.
11pub trait HasOpposite: private::Sealed {
12 type Opposite;
13}
14
15impl HasOpposite for LittleEndian {
16 type Opposite = BigEndian;
17}
18
19impl HasOpposite for BigEndian {
20 type Opposite = LittleEndian;
21}
22
23/// Trait for identifying whether a type is representative of the system's
24/// native byte order.
25pub trait StaticNative: private::Sealed {
26 /// Checks whether this type represents the system's native endianness.
27 fn is_native() -> bool;
28}
29
30impl StaticNative for NativeEndian {
31 fn is_native() -> bool {
32 true
33 }
34}
35
36#[cfg(target_endian = "little")]
37impl StaticNative for BigEndian {
38 fn is_native() -> bool {
39 false
40 }
41}
42
43#[cfg(target_endian = "big")]
44impl StaticNative for LittleEndian {
45 fn is_native() -> bool {
46 false
47 }
48}
49
50/// General trait for types that can
51/// serialize and deserialize bytes in some byte order.
52///
53/// The trait roughly resembles [`byteorder::ByteOrder`],
54/// with the exception that it is implemented for material types,
55/// which are also `Copy`,
56/// and all methods receive `self`.
57/// This makes it possible to embed byte order information to a reader or writer
58/// by composition,
59/// which is done by [`ByteOrdered`].
60///
61/// [`byteorder::ByteOrder`]: https://docs.rs/byteorder/*/byteorder/trait.ByteOrder.html
62/// [`ByteOrdered`]: struct.ByteOrdered.html
63pub trait Endian: Copy + private::Sealed {
64 /// A type which can represent a byte order that is opposite to this one.
65 type Opposite;
66
67 /// Checks whether this value represents the system's native endianness.
68 fn is_native(self) -> bool;
69
70 /// Converts the receiver into its opposite.
71 fn into_opposite(self) -> Self::Opposite;
72
73 /// Reads a signed 16 bit integer from the given reader.
74 ///
75 /// # Errors
76 ///
77 /// This method returns the same errors as [`Read::read_exact`].
78 ///
79 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
80 fn read_i16<R>(self, reader: R) -> IoResult<i16>
81 where
82 R: Read;
83
84 /// Reads a sequence of signed 16 bit integers from the given reader.
85 ///
86 /// The given buffer is either filled completely or an error is returned.
87 /// If an error is returned,
88 /// the contents of `dst` are unspecified.
89 ///
90 /// # Errors
91 ///
92 /// This method returns the same errors as [`Read::read_exact`].
93 ///
94 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
95 fn read_i16_into<R>(self, mut reader: R, dst: &mut [i16]) -> IoResult<()>
96 where
97 R: Read,
98 {
99 for e in dst.iter_mut() {
100 *e = self.read_i16(&mut reader)?;
101 }
102 Ok(())
103 }
104
105 /// Reads an unsigned 16 bit integer from the given reader.
106 ///
107 /// # Errors
108 ///
109 /// This method returns the same errors as [`Read::read_exact`].
110 ///
111 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
112 fn read_u16<R>(self, reader: R) -> IoResult<u16>
113 where
114 R: Read;
115
116 /// Reads a sequence of unsigned 16 bit integers from the given reader.
117 ///
118 /// The given buffer is either filled completely or an error is returned.
119 /// If an error is returned,
120 /// the contents of `dst` are unspecified.
121 ///
122 /// # Errors
123 ///
124 /// This method returns the same errors as [`Read::read_exact`].
125 ///
126 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
127 fn read_u16_into<R>(self, mut reader: R, dst: &mut [u16]) -> IoResult<()>
128 where
129 R: Read,
130 {
131 for e in dst.iter_mut() {
132 *e = self.read_u16(&mut reader)?;
133 }
134 Ok(())
135 }
136
137 /// Reads a signed 32 bit integer from the given reader.
138 ///
139 /// # Errors
140 ///
141 /// This method returns the same errors as [`Read::read_exact`].
142 ///
143 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
144 fn read_i32<R>(self, reader: R) -> IoResult<i32>
145 where
146 R: Read;
147
148 /// Reads a sequence of signed 32 bit integers from the given reader.
149 ///
150 /// The given buffer is either filled completely or an error is returned.
151 /// If an error is returned,
152 /// the contents of `dst` are unspecified.
153 ///
154 /// # Errors
155 ///
156 /// This method returns the same errors as [`Read::read_exact`].
157 ///
158 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
159 fn read_i32_into<R>(self, mut reader: R, dst: &mut [i32]) -> IoResult<()>
160 where
161 R: Read,
162 {
163 for e in dst.iter_mut() {
164 *e = self.read_i32(&mut reader)?;
165 }
166 Ok(())
167 }
168
169 /// Reads an unsigned 32 bit integer from the given reader.
170 ///
171 /// # Errors
172 ///
173 /// This method returns the same errors as [`Read::read_exact`].
174 ///
175 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
176 fn read_u32<R>(self, reader: R) -> IoResult<u32>
177 where
178 R: Read;
179
180 /// Reads a sequence of unsigned 32 bit integers from the given reader.
181 ///
182 /// The given buffer is either filled completely or an error is returned.
183 /// If an error is returned,
184 /// the contents of `dst` are unspecified.
185 ///
186 /// # Errors
187 ///
188 /// This method returns the same errors as [`Read::read_exact`].
189 ///
190 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
191 fn read_u32_into<R>(self, mut reader: R, dst: &mut [u32]) -> IoResult<()>
192 where
193 R: Read,
194 {
195 for e in dst.iter_mut() {
196 *e = self.read_u32(&mut reader)?;
197 }
198 Ok(())
199 }
200
201 /// Reads a signed 64 bit integer from the given reader.
202 ///
203 /// # Errors
204 ///
205 /// This method returns the same errors as [`Read::read_exact`].
206 ///
207 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
208 fn read_i64<R>(self, reader: R) -> IoResult<i64>
209 where
210 R: Read;
211
212 /// Reads a sequence of signed 64 bit integers from the given reader.
213 ///
214 /// The given buffer is either filled completely or an error is returned.
215 /// If an error is returned,
216 /// the contents of `dst` are unspecified.
217 ///
218 /// # Errors
219 ///
220 /// This method returns the same errors as [`Read::read_exact`].
221 ///
222 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
223 fn read_i64_into<R>(self, mut reader: R, dst: &mut [i64]) -> IoResult<()>
224 where
225 R: Read,
226 {
227 for e in dst.iter_mut() {
228 *e = self.read_i64(&mut reader)?;
229 }
230 Ok(())
231 }
232
233 /// Reads an unsigned 64 bit integer from the given reader.
234 ///
235 /// # Errors
236 ///
237 /// This method returns the same errors as [`Read::read_exact`].
238 ///
239 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
240 fn read_u64<R>(self, reader: R) -> IoResult<u64>
241 where
242 R: Read;
243
244 /// Reads a sequence of unsigned 64 bit integers from the given reader.
245 ///
246 /// The given buffer is either filled completely or an error is returned.
247 /// If an error is returned,
248 /// the contents of `dst` are unspecified.
249 ///
250 /// # Errors
251 ///
252 /// This method returns the same errors as [`Read::read_exact`].
253 ///
254 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
255 fn read_u64_into<R>(self, mut reader: R, dst: &mut [u64]) -> IoResult<()>
256 where
257 R: Read,
258 {
259 for e in dst.iter_mut() {
260 *e = self.read_u64(&mut reader)?;
261 }
262 Ok(())
263 }
264
265 /// Reads a signed 128 bit integer from the given reader.
266 ///
267 /// # Errors
268 ///
269 /// This method returns the same errors as [`Read::read_exact`].
270 ///
271 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
272 fn read_i128<R>(self, reader: R) -> IoResult<i128>
273 where
274 R: Read;
275
276 /// Reads a sequence of signed 128 bit integers from the given reader.
277 ///
278 /// The given buffer is either filled completely or an error is returned.
279 /// If an error is returned,
280 /// the contents of `dst` are unspecified.
281 ///
282 /// # Errors
283 ///
284 /// This method returns the same errors as [`Read::read_exact`].
285 ///
286 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
287 fn read_i128_into<R>(self, mut reader: R, dst: &mut [i128]) -> IoResult<()>
288 where
289 R: Read,
290 {
291 for e in dst.iter_mut() {
292 *e = self.read_i128(&mut reader)?;
293 }
294 Ok(())
295 }
296
297 /// Reads an unsigned 128 bit integer from the given reader.
298 ///
299 /// # Errors
300 ///
301 /// This method returns the same errors as [`Read::read_exact`].
302 ///
303 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
304 fn read_u128<R>(self, reader: R) -> IoResult<u128>
305 where
306 R: Read;
307
308 /// Reads a sequence of unsigned 128 bit integers from the given reader.
309 ///
310 /// The given buffer is either filled completely or an error is returned.
311 /// If an error is returned,
312 /// the contents of `dst` are unspecified.
313 ///
314 /// # Errors
315 ///
316 /// This method returns the same errors as [`Read::read_exact`].
317 ///
318 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
319 fn read_u128_into<R>(self, mut reader: R, dst: &mut [u128]) -> IoResult<()>
320 where
321 R: Read,
322 {
323 for e in dst.iter_mut() {
324 *e = self.read_u128(&mut reader)?;
325 }
326 Ok(())
327 }
328
329 /// Reads a IEEE754 single-precision (4 bytes) floating point number from
330 /// the given reader.
331 ///
332 /// # Errors
333 ///
334 /// This method returns the same errors as [`Read::read_exact`].
335 ///
336 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
337 fn read_f32<R>(self, reader: R) -> IoResult<f32>
338 where
339 R: Read;
340
341 /// Reads a sequence of IEEE754 single-precision (4 bytes) floating point numbers
342 /// from the given reader.
343 ///
344 /// The given buffer is either filled completely or an error is returned.
345 /// If an error is returned,
346 /// the contents of `dst` are unspecified.
347 ///
348 /// # Errors
349 ///
350 /// This method returns the same errors as [`Read::read_exact`].
351 ///
352 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
353 fn read_f32_into<R>(self, mut reader: R, dst: &mut [f32]) -> IoResult<()>
354 where
355 R: Read,
356 {
357 for e in dst.iter_mut() {
358 *e = self.read_f32(&mut reader)?;
359 }
360 Ok(())
361 }
362
363 /// Reads a IEEE754 double-precision (8 bytes) floating point number from
364 /// the given reader.
365 ///
366 /// # Errors
367 ///
368 /// This method returns the same errors as [`Read::read_exact`].
369 ///
370 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
371 fn read_f64<R>(self, reader: R) -> IoResult<f64>
372 where
373 R: Read;
374
375 /// Reads a sequence of IEEE754 double-precision (8 bytes) floating point numbers
376 /// from the given reader.
377 ///
378 /// The given buffer is either filled completely or an error is returned.
379 /// If an error is returned,
380 /// the contents of `dst` are unspecified.
381 ///
382 /// # Errors
383 ///
384 /// This method returns the same errors as [`Read::read_exact`].
385 ///
386 /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
387 fn read_f64_into<R>(self, mut reader: R, dst: &mut [f64]) -> IoResult<()>
388 where
389 R: Read,
390 {
391 for e in dst.iter_mut() {
392 *e = self.read_f64(&mut reader)?;
393 }
394 Ok(())
395 }
396
397 /// Writes a signed 16 bit integer to the given writer.
398 ///
399 /// # Errors
400 ///
401 /// This method returns the same errors as [`Write::write_all`].
402 ///
403 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
404 fn write_i16<W>(self, writer: W, v: i16) -> IoResult<()>
405 where
406 W: Write;
407
408 /// Writes an unsigned 16 bit integer to the given writer.
409 ///
410 /// # Errors
411 ///
412 /// This method returns the same errors as [`Write::write_all`].
413 ///
414 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
415 fn write_u16<W>(self, writer: W, v: u16) -> IoResult<()>
416 where
417 W: Write;
418
419 /// Writes a signed 32 bit integer to the given writer.
420 ///
421 /// # Errors
422 ///
423 /// This method returns the same errors as [`Write::write_all`].
424 ///
425 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
426 fn write_i32<W>(self, writer: W, v: i32) -> IoResult<()>
427 where
428 W: Write;
429
430 /// Writes an unsigned 32 bit integer to the given writer.
431 ///
432 /// # Errors
433 ///
434 /// This method returns the same errors as [`Write::write_all`].
435 ///
436 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
437 fn write_u32<W>(self, writer: W, v: u32) -> IoResult<()>
438 where
439 W: Write;
440
441 /// Writes a signed 64 bit integer to the given writer.
442 ///
443 /// # Errors
444 ///
445 /// This method returns the same errors as [`Write::write_all`].
446 ///
447 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
448 fn write_i64<W>(self, writer: W, v: i64) -> IoResult<()>
449 where
450 W: Write;
451
452 /// Writes an unsigned 64 bit integer to the given writer.
453 ///
454 /// # Errors
455 ///
456 /// This method returns the same errors as [`Write::write_all`].
457 ///
458 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
459 fn write_u64<W>(self, writer: W, v: u64) -> IoResult<()>
460 where
461 W: Write;
462
463 /// Writes a signed 128 bit integer to the given writer.
464 ///
465 /// # Errors
466 ///
467 /// This method returns the same errors as [`Write::write_all`].
468 ///
469 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
470 fn write_i128<W>(self, writer: W, v: i128) -> IoResult<()>
471 where
472 W: Write;
473
474 /// Writes an unsigned 128 bit integer to the given writer.
475 ///
476 /// # Errors
477 ///
478 /// This method returns the same errors as [`Write::write_all`].
479 ///
480 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
481 fn write_u128<W>(self, writer: W, v: u128) -> IoResult<()>
482 where
483 W: Write;
484
485 /// Writes a IEEE754 single-precision (4 bytes) floating point number to
486 /// the given writer.
487 ///
488 /// # Errors
489 ///
490 /// This method returns the same errors as [`Write::write_all`].
491 ///
492 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
493 fn write_f32<W>(self, writer: W, v: f32) -> IoResult<()>
494 where
495 W: Write;
496
497 /// Writes a IEEE754 double-precision (8 bytes) floating point number to
498 /// the given writer.
499 ///
500 /// # Errors
501 ///
502 /// This method returns the same errors as [`Write::write_all`].
503 ///
504 /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
505 fn write_f64<W>(self, writer: W, v: f64) -> IoResult<()>
506 where
507 W: Write;
508}
509
510/// A data type representing a byte order known in compile time.
511/// Unlike the types provided in `byteorder`, this type can be constructed.
512///
513/// The parameter type `E` can be one of either [`byteorder::BigEndian`][be]
514/// or [`byteorder::LittleEndian`][le].
515///
516/// [be]: https://docs.rs/byteorder/*/byteorder/enum.BigEndian.html
517/// [le]: https://docs.rs/byteorder/*/byteorder/enum.LittleEndian.html
518#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
519pub struct StaticEndianness<E>(PhantomData<E>);
520
521impl<E> Default for StaticEndianness<E> {
522 #[inline]
523 fn default() -> Self {
524 StaticEndianness::new()
525 }
526}
527
528impl<E> StaticEndianness<E> {
529 /// Constructor for a static endianness.
530 #[inline]
531 pub fn new() -> Self {
532 StaticEndianness(PhantomData)
533 }
534}
535
536impl StaticEndianness<NativeEndian> {
537 /// Constructor for native endianness.
538 #[inline]
539 pub fn native() -> Self {
540 StaticEndianness::new()
541 }
542}
543
544impl PartialEq<StaticEndianness<LittleEndian>> for StaticEndianness<BigEndian> {
545 #[inline]
546 fn eq(&self, _: &StaticEndianness<LittleEndian>) -> bool {
547 false
548 }
549}
550
551impl PartialEq<StaticEndianness<BigEndian>> for StaticEndianness<LittleEndian> {
552 #[inline]
553 fn eq(&self, _: &StaticEndianness<BigEndian>) -> bool {
554 false
555 }
556}
557
558impl PartialEq<Endianness> for StaticEndianness<BigEndian> {
559 #[inline]
560 fn eq(&self, e: &Endianness) -> bool {
561 *e == Endianness::Big
562 }
563}
564
565impl PartialEq<Endianness> for StaticEndianness<LittleEndian> {
566 #[inline]
567 fn eq(&self, e: &Endianness) -> bool {
568 *e == Endianness::Little
569 }
570}
571
572impl<E> HasOpposite for StaticEndianness<E>
573where
574 E: HasOpposite,
575{
576 type Opposite = StaticEndianness<E::Opposite>;
577}
578
579/// Private macro for endiannesses known at compile time,
580/// which implements a `read_*` method
581/// by delegating a call to the same method on `ReadBytesExt`.
582macro_rules! fn_static_endianness_read {
583 ($method:ident, $e:ty, $out:ty) => {
584 #[inline]
585 fn $method<S>(self, mut src: S) -> IoResult<$out>
586 where
587 S: Read,
588 {
589 src.$method::<$e>()
590 }
591 };
592}
593
594/// Private macro for endiannesses known at compile time,
595/// which implements a `read_*_into` method
596/// by delegating a call to the same method on `ReadBytesExt`.
597macro_rules! fn_static_endianness_read_into {
598 ($method:ident, $e:ty, $out:ty) => {
599 #[inline]
600 fn $method<S>(self, mut src: S, dst: &mut [$out]) -> IoResult<()>
601 where
602 S: Read,
603 {
604 src.$method::<$e>(dst)
605 }
606 };
607}
608
609/// Private macro for endiannesses known at compile time,
610/// which implements a `write_*` method
611/// by delegating a call to the same method on `WriteBytesExt`.
612macro_rules! fn_static_endianness_write {
613 ($method:ident, $e:ty, $out:ty) => {
614 #[inline]
615 fn $method<W>(self, mut src: W, x: $out) -> IoResult<()>
616 where
617 W: Write,
618 {
619 src.$method::<$e>(x)
620 }
621 };
622}
623
624impl<E> Endian for StaticEndianness<E>
625where
626 E: HasOpposite,
627 E: StaticNative,
628 E: ByteOrder,
629{
630 type Opposite = StaticEndianness<E::Opposite>;
631
632 #[inline]
633 fn into_opposite(self) -> Self::Opposite {
634 StaticEndianness(PhantomData)
635 }
636
637 #[inline]
638 fn is_native(self) -> bool {
639 E::is_native()
640 }
641
642 fn_static_endianness_read!(read_i16, E, i16);
643 fn_static_endianness_read!(read_u16, E, u16);
644 fn_static_endianness_read!(read_i32, E, i32);
645 fn_static_endianness_read!(read_u32, E, u32);
646 fn_static_endianness_read!(read_i64, E, i64);
647 fn_static_endianness_read!(read_u64, E, u64);
648 fn_static_endianness_read!(read_i128, E, i128);
649 fn_static_endianness_read!(read_u128, E, u128);
650 fn_static_endianness_read!(read_f32, E, f32);
651 fn_static_endianness_read!(read_f64, E, f64);
652
653 fn_static_endianness_read_into!(read_i16_into, E, i16);
654 fn_static_endianness_read_into!(read_u16_into, E, u16);
655 fn_static_endianness_read_into!(read_i32_into, E, i32);
656 fn_static_endianness_read_into!(read_u32_into, E, u32);
657 fn_static_endianness_read_into!(read_i64_into, E, i64);
658 fn_static_endianness_read_into!(read_u64_into, E, u64);
659 fn_static_endianness_read_into!(read_i128_into, E, i128);
660 fn_static_endianness_read_into!(read_u128_into, E, u128);
661 fn_static_endianness_read_into!(read_f32_into, E, f32);
662 fn_static_endianness_read_into!(read_f64_into, E, f64);
663
664 fn_static_endianness_write!(write_i16, E, i16);
665 fn_static_endianness_write!(write_u16, E, u16);
666 fn_static_endianness_write!(write_i32, E, i32);
667 fn_static_endianness_write!(write_u32, E, u32);
668 fn_static_endianness_write!(write_i64, E, i64);
669 fn_static_endianness_write!(write_u64, E, u64);
670 fn_static_endianness_write!(write_i128, E, i128);
671 fn_static_endianness_write!(write_u128, E, u128);
672 fn_static_endianness_write!(write_f32, E, f32);
673 fn_static_endianness_write!(write_f64, E, f64);
674}
675
676/// Enumerate for materializing
677/// the two kinds of machine byte order supported by Rust
678/// in a dynamic fashion.
679/// That is,
680/// the information of whether to read or write data
681/// in Little Endian or in Big Endian
682/// is resolved at run time by observing this value.
683///
684/// Using this type as the generic endianness type `E` in a `ByteOrdered`
685/// is useful when this information can only be retrieved
686/// from a source that is unknown to the compiler.
687#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
688pub enum Endianness {
689 /// Little Endian
690 Little,
691 /// Big Endian
692 Big,
693}
694
695impl From<StaticEndianness<LittleEndian>> for Endianness {
696 #[inline]
697 fn from(_: StaticEndianness<LittleEndian>) -> Self {
698 Endianness::Little
699 }
700}
701
702impl From<StaticEndianness<BigEndian>> for Endianness {
703 #[inline]
704 fn from(_: StaticEndianness<BigEndian>) -> Self {
705 Endianness::Big
706 }
707}
708
709impl PartialEq<StaticEndianness<BigEndian>> for Endianness {
710 #[inline]
711 fn eq(&self, _: &StaticEndianness<BigEndian>) -> bool {
712 *self == Endianness::Big
713 }
714}
715
716impl PartialEq<StaticEndianness<LittleEndian>> for Endianness {
717 #[inline]
718 fn eq(&self, _: &StaticEndianness<LittleEndian>) -> bool {
719 *self == Endianness::Little
720 }
721}
722
723/// Private macro for endiannesses known at run time,
724/// which implements a `read_*` method
725/// by delegating a call to the same method on `ReadBytesExt`.
726macro_rules! fn_runtime_endianness_read {
727 ($method:ident, $out:ty) => {
728 #[inline]
729 fn $method<S>(self, mut src: S) -> IoResult<$out>
730 where
731 S: Read,
732 {
733 match self {
734 Endianness::Little => src.$method::<LittleEndian>(),
735 Endianness::Big => src.$method::<BigEndian>(),
736 }
737 }
738 };
739}
740
741/// Private macro for endiannesses known at run time,
742/// which implements a `read_*_into` method
743/// by delegating a call to the same method on `ReadBytesExt`.
744macro_rules! fn_runtime_endianness_read_into {
745 ($method:ident, $out:ty) => {
746 #[inline]
747 fn $method<S>(self, mut src: S, dst: &mut [$out]) -> IoResult<()>
748 where
749 S: Read,
750 {
751 match self {
752 Endianness::Little => src.$method::<LittleEndian>(dst),
753 Endianness::Big => src.$method::<BigEndian>(dst),
754 }
755 }
756 };
757}
758
759/// Private macro for endiannesses known at run time,
760/// which implements a `write_*` method
761/// by delegating a call to the same method on `WriteBytesExt`.
762macro_rules! fn_runtime_endianness_write {
763 ($method:ident, $i:ty) => {
764 #[inline]
765 fn $method<S>(self, mut src: S, v: $i) -> IoResult<()>
766 where
767 S: Write,
768 {
769 match self {
770 Endianness::Little => src.$method::<LittleEndian>(v),
771 Endianness::Big => src.$method::<BigEndian>(v),
772 }
773 }
774 };
775}
776
777impl HasOpposite for Endianness {
778 type Opposite = Self;
779}
780
781impl Endian for Endianness {
782 type Opposite = Self;
783
784 #[inline]
785 fn into_opposite(self) -> Self::Opposite {
786 self.to_opposite()
787 }
788
789 #[inline]
790 fn is_native(self) -> bool {
791 self == Endianness::native()
792 }
793
794 fn_runtime_endianness_read!(read_i16, i16);
795 fn_runtime_endianness_read!(read_u16, u16);
796 fn_runtime_endianness_read!(read_i32, i32);
797 fn_runtime_endianness_read!(read_u32, u32);
798 fn_runtime_endianness_read!(read_i64, i64);
799 fn_runtime_endianness_read!(read_u64, u64);
800 fn_runtime_endianness_read!(read_f32, f32);
801 fn_runtime_endianness_read!(read_f64, f64);
802 fn_runtime_endianness_read!(read_i128, i128);
803 fn_runtime_endianness_read!(read_u128, u128);
804
805 fn_runtime_endianness_read_into!(read_i16_into, i16);
806 fn_runtime_endianness_read_into!(read_u16_into, u16);
807 fn_runtime_endianness_read_into!(read_i32_into, i32);
808 fn_runtime_endianness_read_into!(read_u32_into, u32);
809 fn_runtime_endianness_read_into!(read_i64_into, i64);
810 fn_runtime_endianness_read_into!(read_u64_into, u64);
811 fn_runtime_endianness_read_into!(read_f32_into, f32);
812 fn_runtime_endianness_read_into!(read_f64_into, f64);
813 fn_runtime_endianness_read_into!(read_i128_into, i128);
814 fn_runtime_endianness_read_into!(read_u128_into, u128);
815
816 fn_runtime_endianness_write!(write_i16, i16);
817 fn_runtime_endianness_write!(write_u16, u16);
818 fn_runtime_endianness_write!(write_i32, i32);
819 fn_runtime_endianness_write!(write_u32, u32);
820 fn_runtime_endianness_write!(write_i64, i64);
821 fn_runtime_endianness_write!(write_u64, u64);
822 fn_runtime_endianness_write!(write_f32, f32);
823 fn_runtime_endianness_write!(write_f64, f64);
824 fn_runtime_endianness_write!(write_i128, i128);
825 fn_runtime_endianness_write!(write_u128, u128);
826}
827
828impl Endianness {
829 /// Obtains this system's native endianness.
830 ///
831 /// On this platform, the function returns `Endianness::Little`.
832 #[cfg(target_endian = "little")]
833 #[inline]
834 pub fn native() -> Self {
835 Endianness::Little
836 }
837
838 /// Obtains this system's native endianness.
839 ///
840 /// On this platform, the function returns `Endianness::Big`.
841 #[cfg(target_endian = "big")]
842 #[inline]
843 pub fn native() -> Self {
844 Endianness::Big
845 }
846
847 /// Obtains _Little Endian_ if and only if the given value is `true`.
848 ///
849 /// # Examples
850 ///
851 /// ```
852 /// # use byteordered::{Endian, Endianness};
853 /// let data: &[u8] = &[4, 1];
854 /// let e = Endianness::le_iff(2 + 2 == 4);
855 /// assert_eq!(e.read_u16(data).unwrap(), 260);
856 ///
857 /// let e = Endianness::le_iff(2 + 2 >= 5);
858 /// assert_eq!(e.read_u16(data).unwrap(), 1025);
859 /// ```
860 #[inline]
861 pub fn le_iff(e: bool) -> Self {
862 if e {
863 Endianness::Little
864 } else {
865 Endianness::Big
866 }
867 }
868
869 /// Obtains _Big Endian_ if and only if the given value is `true`.
870 ///
871 /// Examples
872 ///
873 /// ```
874 /// # use byteordered::Endianness;
875 /// assert_eq!(Endianness::be_iff(2 + 2 == 4), Endianness::Big);
876 /// assert_eq!(Endianness::be_iff(2 + 2 >= 5), Endianness::Little);
877 /// ```
878 #[inline]
879 pub fn be_iff(e: bool) -> Self {
880 if e {
881 Endianness::Big
882 } else {
883 Endianness::Little
884 }
885 }
886
887 /// Obtains the opposite endianness: Little Endian returns Big Endian and vice versa.
888 #[inline]
889 pub fn to_opposite(self) -> Self {
890 if self == Endianness::Little {
891 Endianness::Big
892 } else {
893 Endianness::Little
894 }
895 }
896}
897
898mod private {
899 use super::{Endianness, StaticEndianness};
900 use byteorder::{BigEndian, LittleEndian};
901 pub trait Sealed {}
902
903 impl Sealed for LittleEndian {}
904 impl Sealed for BigEndian {}
905 impl<T> Sealed for StaticEndianness<T> {}
906 impl Sealed for Endianness {}
907}
908
909#[cfg(test)]
910mod tests {
911 use super::*;
912 /// the test bytes for testing integer type reading
913 static TEST_BYTES: &'static [u8] = &[0x12, 0x34, 0x56, 0x78, 0x21, 0x43, 0x65, 0x87];
914
915 /// the test bytes as a single u64 in little endian
916 static TEST_U64DATA_LE: &'static [u64] = &[0x87654321_78563412];
917 /// the test bytes as a single u64 in big endian
918 static TEST_U64DATA_BE: &'static [u64] = &[0x12345678_21436587];
919
920 #[test]
921 fn test_read_u64() {
922 let mut data = TEST_BYTES;
923 let e = Endianness::Little;
924 let words = [e.read_u64(&mut data).unwrap()];
925 assert_eq!(words, TEST_U64DATA_LE);
926
927 let mut data = TEST_BYTES;
928 let e = Endianness::Big;
929 let words = [e.read_u64(&mut data).unwrap()];
930 assert_eq!(words, TEST_U64DATA_BE);
931 }
932
933 /// the test bytes as two u32s in little endian
934 static TEST_U32DATA_LE: &'static [u32] = &[0x7856_3412, 0x8765_4321];
935 /// the test bytes as two u32s in big endian
936 static TEST_U32DATA_BE: &'static [u32] = &[0x1234_5678, 0x2143_6587];
937
938 #[test]
939 fn test_read_u32() {
940 let mut data = TEST_BYTES;
941 let e = Endianness::Little;
942 let words = [
943 e.read_u32(&mut data).unwrap(),
944 e.read_u32(&mut data).unwrap(),
945 ];
946 assert_eq!(words, TEST_U32DATA_LE);
947
948 let mut data = TEST_BYTES;
949 let e = Endianness::Big;
950 let words = [
951 e.read_u32(&mut data).unwrap(),
952 e.read_u32(&mut data).unwrap(),
953 ];
954 assert_eq!(words, TEST_U32DATA_BE);
955 }
956
957 /// the test bytes as four u16s in little endian
958 static TEST_U16DATA_LE: &'static [u16] = &[0x3412, 0x7856, 0x4321, 0x8765];
959 /// the test bytes as four u16s in big endian
960 static TEST_U16DATA_BE: &'static [u16] = &[0x1234, 0x5678, 0x2143, 0x6587];
961
962 #[test]
963 fn test_read_u16() {
964 let mut data = TEST_BYTES;
965 let e = Endianness::Little;
966 let words = [
967 e.read_u16(&mut data).unwrap(),
968 e.read_u16(&mut data).unwrap(),
969 e.read_u16(&mut data).unwrap(),
970 e.read_u16(&mut data).unwrap(),
971 ];
972 assert_eq!(words, TEST_U16DATA_LE);
973
974 let mut data = TEST_BYTES;
975 let e = Endianness::Big;
976 let words = [
977 e.read_u16(&mut data).unwrap(),
978 e.read_u16(&mut data).unwrap(),
979 e.read_u16(&mut data).unwrap(),
980 e.read_u16(&mut data).unwrap(),
981 ];
982 assert_eq!(words, TEST_U16DATA_BE);
983 }
984
985 #[test]
986 fn test_read_u16_into() {
987 let data = TEST_BYTES;
988
989 let e = Endianness::Little;
990 let mut words = [0; 4];
991 e.read_u16_into(&mut &data[..], &mut words).unwrap();
992 assert_eq!(words, TEST_U16DATA_LE);
993
994 let e = Endianness::Big;
995 let mut words = [0; 4];
996 e.read_u16_into(&mut &data[..], &mut words).unwrap();
997 assert_eq!(words, TEST_U16DATA_BE);
998 }
999
1000 #[test]
1001 fn test_read_u32_into() {
1002 let data = TEST_BYTES;
1003
1004 let e = Endianness::Little;
1005 let mut words = [0; 2];
1006 e.read_u32_into(&mut &data[..], &mut words).unwrap();
1007 assert_eq!(words, TEST_U32DATA_LE);
1008
1009 let e = Endianness::Big;
1010 let mut words = [0; 2];
1011 e.read_u32_into(&mut &data[..], &mut words).unwrap();
1012 assert_eq!(words, TEST_U32DATA_BE);
1013 }
1014
1015 #[test]
1016 fn test_native_is_le() {
1017 if cfg!(target_endian = "little") {
1018 assert_eq!(Endianness::native(), Endianness::Little);
1019 } else if cfg!(target_endian = "big") {
1020 assert_eq!(Endianness::native(), Endianness::Big);
1021 } else {
1022 unreachable!();
1023 }
1024 }
1025
1026 // TODO test writing
1027}