1 //! Types for compile-time and run-time endianness. 2 3 use crate::pod::Pod; 4 use core::fmt::{self, Debug}; 5 use core::marker::PhantomData; 6 7 /// A trait for using an endianness specification. 8 /// 9 /// Provides methods for converting between the specified endianness and 10 /// the native endianness of the target machine. 11 /// 12 /// This trait does not require that the endianness is known at compile time. 13 pub trait Endian: Debug + Default + Clone + Copy + PartialEq + Eq + 'static { 14 /// Construct a specification for the endianness of some values. 15 /// 16 /// Returns `None` if the type does not support specifying the given endianness. from_big_endian(big_endian: bool) -> Option<Self>17 fn from_big_endian(big_endian: bool) -> Option<Self>; 18 19 /// Construct a specification for the endianness of some values. 20 /// 21 /// Returns `None` if the type does not support specifying the given endianness. from_little_endian(little_endian: bool) -> Option<Self>22 fn from_little_endian(little_endian: bool) -> Option<Self> { 23 Self::from_big_endian(!little_endian) 24 } 25 26 /// Return true for big endian byte order. is_big_endian(self) -> bool27 fn is_big_endian(self) -> bool; 28 29 /// Return true for little endian byte order. 30 #[inline] is_little_endian(self) -> bool31 fn is_little_endian(self) -> bool { 32 !self.is_big_endian() 33 } 34 35 /// Converts an unsigned 16 bit integer to native endian. 36 #[inline] read_u16(self, n: u16) -> u1637 fn read_u16(self, n: u16) -> u16 { 38 if self.is_big_endian() { 39 u16::from_be(n) 40 } else { 41 u16::from_le(n) 42 } 43 } 44 45 /// Converts an unsigned 32 bit integer to native endian. 46 #[inline] read_u32(self, n: u32) -> u3247 fn read_u32(self, n: u32) -> u32 { 48 if self.is_big_endian() { 49 u32::from_be(n) 50 } else { 51 u32::from_le(n) 52 } 53 } 54 55 /// Converts an unsigned 64 bit integer to native endian. 56 #[inline] read_u64(self, n: u64) -> u6457 fn read_u64(self, n: u64) -> u64 { 58 if self.is_big_endian() { 59 u64::from_be(n) 60 } else { 61 u64::from_le(n) 62 } 63 } 64 65 /// Converts a signed 16 bit integer to native endian. 66 #[inline] read_i16(self, n: i16) -> i1667 fn read_i16(self, n: i16) -> i16 { 68 if self.is_big_endian() { 69 i16::from_be(n) 70 } else { 71 i16::from_le(n) 72 } 73 } 74 75 /// Converts a signed 32 bit integer to native endian. 76 #[inline] read_i32(self, n: i32) -> i3277 fn read_i32(self, n: i32) -> i32 { 78 if self.is_big_endian() { 79 i32::from_be(n) 80 } else { 81 i32::from_le(n) 82 } 83 } 84 85 /// Converts a signed 64 bit integer to native endian. 86 #[inline] read_i64(self, n: i64) -> i6487 fn read_i64(self, n: i64) -> i64 { 88 if self.is_big_endian() { 89 i64::from_be(n) 90 } else { 91 i64::from_le(n) 92 } 93 } 94 95 /// Converts an unaligned unsigned 16 bit integer to native endian. 96 #[inline] read_u16_bytes(self, n: [u8; 2]) -> u1697 fn read_u16_bytes(self, n: [u8; 2]) -> u16 { 98 if self.is_big_endian() { 99 u16::from_be_bytes(n) 100 } else { 101 u16::from_le_bytes(n) 102 } 103 } 104 105 /// Converts an unaligned unsigned 32 bit integer to native endian. 106 #[inline] read_u32_bytes(self, n: [u8; 4]) -> u32107 fn read_u32_bytes(self, n: [u8; 4]) -> u32 { 108 if self.is_big_endian() { 109 u32::from_be_bytes(n) 110 } else { 111 u32::from_le_bytes(n) 112 } 113 } 114 115 /// Converts an unaligned unsigned 64 bit integer to native endian. 116 #[inline] read_u64_bytes(self, n: [u8; 8]) -> u64117 fn read_u64_bytes(self, n: [u8; 8]) -> u64 { 118 if self.is_big_endian() { 119 u64::from_be_bytes(n) 120 } else { 121 u64::from_le_bytes(n) 122 } 123 } 124 125 /// Converts an unaligned signed 16 bit integer to native endian. 126 #[inline] read_i16_bytes(self, n: [u8; 2]) -> i16127 fn read_i16_bytes(self, n: [u8; 2]) -> i16 { 128 if self.is_big_endian() { 129 i16::from_be_bytes(n) 130 } else { 131 i16::from_le_bytes(n) 132 } 133 } 134 135 /// Converts an unaligned signed 32 bit integer to native endian. 136 #[inline] read_i32_bytes(self, n: [u8; 4]) -> i32137 fn read_i32_bytes(self, n: [u8; 4]) -> i32 { 138 if self.is_big_endian() { 139 i32::from_be_bytes(n) 140 } else { 141 i32::from_le_bytes(n) 142 } 143 } 144 145 /// Converts an unaligned signed 64 bit integer to native endian. 146 #[inline] read_i64_bytes(self, n: [u8; 8]) -> i64147 fn read_i64_bytes(self, n: [u8; 8]) -> i64 { 148 if self.is_big_endian() { 149 i64::from_be_bytes(n) 150 } else { 151 i64::from_le_bytes(n) 152 } 153 } 154 155 /// Converts an unsigned 16 bit integer from native endian. 156 #[inline] write_u16(self, n: u16) -> u16157 fn write_u16(self, n: u16) -> u16 { 158 if self.is_big_endian() { 159 u16::to_be(n) 160 } else { 161 u16::to_le(n) 162 } 163 } 164 165 /// Converts an unsigned 32 bit integer from native endian. 166 #[inline] write_u32(self, n: u32) -> u32167 fn write_u32(self, n: u32) -> u32 { 168 if self.is_big_endian() { 169 u32::to_be(n) 170 } else { 171 u32::to_le(n) 172 } 173 } 174 175 /// Converts an unsigned 64 bit integer from native endian. 176 #[inline] write_u64(self, n: u64) -> u64177 fn write_u64(self, n: u64) -> u64 { 178 if self.is_big_endian() { 179 u64::to_be(n) 180 } else { 181 u64::to_le(n) 182 } 183 } 184 185 /// Converts a signed 16 bit integer from native endian. 186 #[inline] write_i16(self, n: i16) -> i16187 fn write_i16(self, n: i16) -> i16 { 188 if self.is_big_endian() { 189 i16::to_be(n) 190 } else { 191 i16::to_le(n) 192 } 193 } 194 195 /// Converts a signed 32 bit integer from native endian. 196 #[inline] write_i32(self, n: i32) -> i32197 fn write_i32(self, n: i32) -> i32 { 198 if self.is_big_endian() { 199 i32::to_be(n) 200 } else { 201 i32::to_le(n) 202 } 203 } 204 205 /// Converts a signed 64 bit integer from native endian. 206 #[inline] write_i64(self, n: i64) -> i64207 fn write_i64(self, n: i64) -> i64 { 208 if self.is_big_endian() { 209 i64::to_be(n) 210 } else { 211 i64::to_le(n) 212 } 213 } 214 215 /// Converts an unaligned unsigned 16 bit integer from native endian. 216 #[inline] write_u16_bytes(self, n: u16) -> [u8; 2]217 fn write_u16_bytes(self, n: u16) -> [u8; 2] { 218 if self.is_big_endian() { 219 u16::to_be_bytes(n) 220 } else { 221 u16::to_le_bytes(n) 222 } 223 } 224 225 /// Converts an unaligned unsigned 32 bit integer from native endian. 226 #[inline] write_u32_bytes(self, n: u32) -> [u8; 4]227 fn write_u32_bytes(self, n: u32) -> [u8; 4] { 228 if self.is_big_endian() { 229 u32::to_be_bytes(n) 230 } else { 231 u32::to_le_bytes(n) 232 } 233 } 234 235 /// Converts an unaligned unsigned 64 bit integer from native endian. 236 #[inline] write_u64_bytes(self, n: u64) -> [u8; 8]237 fn write_u64_bytes(self, n: u64) -> [u8; 8] { 238 if self.is_big_endian() { 239 u64::to_be_bytes(n) 240 } else { 241 u64::to_le_bytes(n) 242 } 243 } 244 245 /// Converts an unaligned signed 16 bit integer from native endian. 246 #[inline] write_i16_bytes(self, n: i16) -> [u8; 2]247 fn write_i16_bytes(self, n: i16) -> [u8; 2] { 248 if self.is_big_endian() { 249 i16::to_be_bytes(n) 250 } else { 251 i16::to_le_bytes(n) 252 } 253 } 254 255 /// Converts an unaligned signed 32 bit integer from native endian. 256 #[inline] write_i32_bytes(self, n: i32) -> [u8; 4]257 fn write_i32_bytes(self, n: i32) -> [u8; 4] { 258 if self.is_big_endian() { 259 i32::to_be_bytes(n) 260 } else { 261 i32::to_le_bytes(n) 262 } 263 } 264 265 /// Converts an unaligned signed 64 bit integer from native endian. 266 #[inline] write_i64_bytes(self, n: i64) -> [u8; 8]267 fn write_i64_bytes(self, n: i64) -> [u8; 8] { 268 if self.is_big_endian() { 269 i64::to_be_bytes(n) 270 } else { 271 i64::to_le_bytes(n) 272 } 273 } 274 } 275 276 /// An endianness that is selectable at run-time. 277 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 278 pub enum Endianness { 279 /// Little endian byte order. 280 Little, 281 /// Big endian byte order. 282 Big, 283 } 284 285 impl Default for Endianness { 286 #[cfg(target_endian = "little")] 287 #[inline] default() -> Endianness288 fn default() -> Endianness { 289 Endianness::Little 290 } 291 292 #[cfg(target_endian = "big")] 293 #[inline] default() -> Endianness294 fn default() -> Endianness { 295 Endianness::Big 296 } 297 } 298 299 impl Endian for Endianness { 300 #[inline] from_big_endian(big_endian: bool) -> Option<Self>301 fn from_big_endian(big_endian: bool) -> Option<Self> { 302 Some(if big_endian { 303 Endianness::Big 304 } else { 305 Endianness::Little 306 }) 307 } 308 309 #[inline] is_big_endian(self) -> bool310 fn is_big_endian(self) -> bool { 311 self != Endianness::Little 312 } 313 } 314 315 /// Compile-time little endian byte order. 316 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 317 pub struct LittleEndian; 318 319 impl Default for LittleEndian { 320 #[inline] default() -> LittleEndian321 fn default() -> LittleEndian { 322 LittleEndian 323 } 324 } 325 326 impl Endian for LittleEndian { 327 #[inline] from_big_endian(big_endian: bool) -> Option<Self>328 fn from_big_endian(big_endian: bool) -> Option<Self> { 329 if big_endian { 330 None 331 } else { 332 Some(LittleEndian) 333 } 334 } 335 336 #[inline] is_big_endian(self) -> bool337 fn is_big_endian(self) -> bool { 338 false 339 } 340 } 341 342 /// Compile-time big endian byte order. 343 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 344 pub struct BigEndian; 345 346 impl Default for BigEndian { 347 #[inline] default() -> BigEndian348 fn default() -> BigEndian { 349 BigEndian 350 } 351 } 352 353 impl Endian for BigEndian { 354 #[inline] from_big_endian(big_endian: bool) -> Option<Self>355 fn from_big_endian(big_endian: bool) -> Option<Self> { 356 if big_endian { 357 Some(BigEndian) 358 } else { 359 None 360 } 361 } 362 363 #[inline] is_big_endian(self) -> bool364 fn is_big_endian(self) -> bool { 365 true 366 } 367 } 368 369 /// The native endianness for the target platform. 370 #[cfg(target_endian = "little")] 371 pub type NativeEndian = LittleEndian; 372 373 #[cfg(target_endian = "little")] 374 #[allow(non_upper_case_globals)] 375 #[doc(hidden)] 376 pub const NativeEndian: LittleEndian = LittleEndian; 377 378 /// The native endianness for the target platform. 379 #[cfg(target_endian = "big")] 380 pub type NativeEndian = BigEndian; 381 382 #[cfg(target_endian = "big")] 383 #[allow(non_upper_case_globals)] 384 #[doc(hidden)] 385 pub const NativeEndian: BigEndian = BigEndian; 386 387 macro_rules! unsafe_impl_endian_pod { 388 ($($struct_name:ident),+ $(,)?) => { 389 $( 390 unsafe impl<E: Endian> Pod for $struct_name<E> { } 391 )+ 392 } 393 } 394 395 #[cfg(not(feature = "unaligned"))] 396 mod aligned { 397 use super::{fmt, Endian, PhantomData, Pod}; 398 399 /// A `u16` value with an externally specified endianness of type `E`. 400 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 401 #[repr(transparent)] 402 pub struct U16<E: Endian>(u16, PhantomData<E>); 403 404 impl<E: Endian> U16<E> { 405 /// Construct a new value given a native endian value. new(e: E, n: u16) -> Self406 pub fn new(e: E, n: u16) -> Self { 407 Self(e.write_u16(n), PhantomData) 408 } 409 410 /// Return the value as a native endian value. get(self, e: E) -> u16411 pub fn get(self, e: E) -> u16 { 412 e.read_u16(self.0) 413 } 414 415 /// Set the value given a native endian value. set(&mut self, e: E, n: u16)416 pub fn set(&mut self, e: E, n: u16) { 417 self.0 = e.write_u16(n); 418 } 419 } 420 421 /// A `u32` value with an externally specified endianness of type `E`. 422 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 423 #[repr(transparent)] 424 pub struct U32<E: Endian>(u32, PhantomData<E>); 425 426 impl<E: Endian> U32<E> { 427 /// Construct a new value given a native endian value. new(e: E, n: u32) -> Self428 pub fn new(e: E, n: u32) -> Self { 429 Self(e.write_u32(n), PhantomData) 430 } 431 /// Return the value as a native endian value. get(self, e: E) -> u32432 pub fn get(self, e: E) -> u32 { 433 e.read_u32(self.0) 434 } 435 /// Set the value given a native endian value. set(&mut self, e: E, n: u32)436 pub fn set(&mut self, e: E, n: u32) { 437 self.0 = e.write_u32(n); 438 } 439 } 440 441 /// A `u64` value with an externally specified endianness of type `E`. 442 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 443 #[repr(transparent)] 444 pub struct U64<E: Endian>(u64, PhantomData<E>); 445 446 impl<E: Endian> U64<E> { 447 /// Construct a new value given a native endian value. new(e: E, n: u64) -> Self448 pub fn new(e: E, n: u64) -> Self { 449 Self(e.write_u64(n), PhantomData) 450 } 451 /// Return the value as a native endian value. get(self, e: E) -> u64452 pub fn get(self, e: E) -> u64 { 453 e.read_u64(self.0) 454 } 455 /// Set the value given a native endian value. set(&mut self, e: E, n: u64)456 pub fn set(&mut self, e: E, n: u64) { 457 self.0 = e.write_u64(n); 458 } 459 } 460 461 /// An `i16` value with an externally specified endianness of type `E`. 462 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 463 #[repr(transparent)] 464 pub struct I16<E: Endian>(i16, PhantomData<E>); 465 466 impl<E: Endian> I16<E> { 467 /// Construct a new value given a native endian value. new(e: E, n: i16) -> Self468 pub fn new(e: E, n: i16) -> Self { 469 Self(e.write_i16(n), PhantomData) 470 } 471 /// Return the value as a native endian value. get(self, e: E) -> i16472 pub fn get(self, e: E) -> i16 { 473 e.read_i16(self.0) 474 } 475 /// Set the value given a native endian value. set(&mut self, e: E, n: i16)476 pub fn set(&mut self, e: E, n: i16) { 477 self.0 = e.write_i16(n); 478 } 479 } 480 481 /// An `i32` value with an externally specified endianness of type `E`. 482 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 483 #[repr(transparent)] 484 pub struct I32<E: Endian>(i32, PhantomData<E>); 485 486 impl<E: Endian> I32<E> { 487 /// Construct a new value given a native endian value. new(e: E, n: i32) -> Self488 pub fn new(e: E, n: i32) -> Self { 489 Self(e.write_i32(n), PhantomData) 490 } 491 /// Return the value as a native endian value. get(self, e: E) -> i32492 pub fn get(self, e: E) -> i32 { 493 e.read_i32(self.0) 494 } 495 /// Set the value given a native endian value. set(&mut self, e: E, n: i32)496 pub fn set(&mut self, e: E, n: i32) { 497 self.0 = e.write_i32(n); 498 } 499 } 500 501 /// An `i64` value with an externally specified endianness of type `E`. 502 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 503 #[repr(transparent)] 504 pub struct I64<E: Endian>(i64, PhantomData<E>); 505 506 impl<E: Endian> I64<E> { 507 /// Construct a new value given a native endian value. new(e: E, n: i64) -> Self508 pub fn new(e: E, n: i64) -> Self { 509 Self(e.write_i64(n), PhantomData) 510 } 511 /// Return the value as a native endian value. get(self, e: E) -> i64512 pub fn get(self, e: E) -> i64 { 513 e.read_i64(self.0) 514 } 515 /// Set the value given a native endian value. set(&mut self, e: E, n: i64)516 pub fn set(&mut self, e: E, n: i64) { 517 self.0 = e.write_i64(n); 518 } 519 } 520 521 impl<E: Endian> fmt::Debug for U16<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 523 write!(f, "U16({:x})", self.0) 524 } 525 } 526 527 impl<E: Endian> fmt::Debug for U32<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 529 write!(f, "U32({:x})", self.0) 530 } 531 } 532 533 impl<E: Endian> fmt::Debug for U64<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 535 write!(f, "U64({:x})", self.0) 536 } 537 } 538 539 impl<E: Endian> fmt::Debug for I16<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 541 write!(f, "I16({:x})", self.0) 542 } 543 } 544 545 impl<E: Endian> fmt::Debug for I32<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result546 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 547 write!(f, "I32({:x})", self.0) 548 } 549 } 550 551 impl<E: Endian> fmt::Debug for I64<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 553 write!(f, "I64({:x})", self.0) 554 } 555 } 556 557 unsafe_impl_endian_pod!(U16, U32, U64, I16, I32, I64); 558 } 559 560 #[cfg(not(feature = "unaligned"))] 561 pub use aligned::*; 562 563 /// A `u16` value with an externally specified endianness of type `E`. 564 #[cfg(feature = "unaligned")] 565 pub type U16<E> = U16Bytes<E>; 566 567 /// A `u32` value with an externally specified endianness of type `E`. 568 #[cfg(feature = "unaligned")] 569 pub type U32<E> = U32Bytes<E>; 570 571 /// A `u64` value with an externally specified endianness of type `E`. 572 #[cfg(feature = "unaligned")] 573 pub type U64<E> = U64Bytes<E>; 574 575 /// An `i16` value with an externally specified endianness of type `E`. 576 #[cfg(feature = "unaligned")] 577 pub type I16<E> = I16Bytes<E>; 578 579 /// An `i32` value with an externally specified endianness of type `E`. 580 #[cfg(feature = "unaligned")] 581 pub type I32<E> = I32Bytes<E>; 582 583 /// An `i64` value with an externally specified endianness of type `E`. 584 #[cfg(feature = "unaligned")] 585 pub type I64<E> = I64Bytes<E>; 586 587 /// An unaligned `u16` value with an externally specified endianness of type `E`. 588 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 589 #[repr(transparent)] 590 pub struct U16Bytes<E: Endian>([u8; 2], PhantomData<E>); 591 592 impl<E: Endian> U16Bytes<E> { 593 /// Construct a new value given a native endian value. new(e: E, n: u16) -> Self594 pub fn new(e: E, n: u16) -> Self { 595 Self(e.write_u16_bytes(n), PhantomData) 596 } 597 598 /// Return the value as a native endian value. get(self, e: E) -> u16599 pub fn get(self, e: E) -> u16 { 600 e.read_u16_bytes(self.0) 601 } 602 603 /// Set the value given a native endian value. set(&mut self, e: E, n: u16)604 pub fn set(&mut self, e: E, n: u16) { 605 self.0 = e.write_u16_bytes(n); 606 } 607 } 608 609 /// An unaligned `u32` value with an externally specified endianness of type `E`. 610 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 611 #[repr(transparent)] 612 pub struct U32Bytes<E: Endian>([u8; 4], PhantomData<E>); 613 614 impl<E: Endian> U32Bytes<E> { 615 /// Construct a new value given a native endian value. new(e: E, n: u32) -> Self616 pub fn new(e: E, n: u32) -> Self { 617 Self(e.write_u32_bytes(n), PhantomData) 618 } 619 620 /// Return the value as a native endian value. get(self, e: E) -> u32621 pub fn get(self, e: E) -> u32 { 622 e.read_u32_bytes(self.0) 623 } 624 625 /// Set the value given a native endian value. set(&mut self, e: E, n: u32)626 pub fn set(&mut self, e: E, n: u32) { 627 self.0 = e.write_u32_bytes(n); 628 } 629 } 630 631 /// An unaligned `u64` value with an externally specified endianness of type `E`. 632 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 633 #[repr(transparent)] 634 pub struct U64Bytes<E: Endian>([u8; 8], PhantomData<E>); 635 636 impl<E: Endian> U64Bytes<E> { 637 /// Construct a new value given a native endian value. new(e: E, n: u64) -> Self638 pub fn new(e: E, n: u64) -> Self { 639 Self(e.write_u64_bytes(n), PhantomData) 640 } 641 642 /// Return the value as a native endian value. get(self, e: E) -> u64643 pub fn get(self, e: E) -> u64 { 644 e.read_u64_bytes(self.0) 645 } 646 647 /// Set the value given a native endian value. set(&mut self, e: E, n: u64)648 pub fn set(&mut self, e: E, n: u64) { 649 self.0 = e.write_u64_bytes(n); 650 } 651 } 652 653 /// An unaligned `i16` value with an externally specified endianness of type `E`. 654 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 655 #[repr(transparent)] 656 pub struct I16Bytes<E: Endian>([u8; 2], PhantomData<E>); 657 658 impl<E: Endian> I16Bytes<E> { 659 /// Construct a new value given a native endian value. new(e: E, n: i16) -> Self660 pub fn new(e: E, n: i16) -> Self { 661 Self(e.write_i16_bytes(n), PhantomData) 662 } 663 664 /// Return the value as a native endian value. get(self, e: E) -> i16665 pub fn get(self, e: E) -> i16 { 666 e.read_i16_bytes(self.0) 667 } 668 669 /// Set the value given a native endian value. set(&mut self, e: E, n: i16)670 pub fn set(&mut self, e: E, n: i16) { 671 self.0 = e.write_i16_bytes(n); 672 } 673 } 674 675 /// An unaligned `i32` value with an externally specified endianness of type `E`. 676 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 677 #[repr(transparent)] 678 pub struct I32Bytes<E: Endian>([u8; 4], PhantomData<E>); 679 680 impl<E: Endian> I32Bytes<E> { 681 /// Construct a new value given a native endian value. new(e: E, n: i32) -> Self682 pub fn new(e: E, n: i32) -> Self { 683 Self(e.write_i32_bytes(n), PhantomData) 684 } 685 686 /// Return the value as a native endian value. get(self, e: E) -> i32687 pub fn get(self, e: E) -> i32 { 688 e.read_i32_bytes(self.0) 689 } 690 691 /// Set the value given a native endian value. set(&mut self, e: E, n: i32)692 pub fn set(&mut self, e: E, n: i32) { 693 self.0 = e.write_i32_bytes(n); 694 } 695 } 696 697 /// An unaligned `i64` value with an externally specified endianness of type `E`. 698 #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 699 #[repr(transparent)] 700 pub struct I64Bytes<E: Endian>([u8; 8], PhantomData<E>); 701 702 impl<E: Endian> I64Bytes<E> { 703 /// Construct a new value given a native endian value. new(e: E, n: i64) -> Self704 pub fn new(e: E, n: i64) -> Self { 705 Self(e.write_i64_bytes(n), PhantomData) 706 } 707 708 /// Return the value as a native endian value. get(self, e: E) -> i64709 pub fn get(self, e: E) -> i64 { 710 e.read_i64_bytes(self.0) 711 } 712 713 /// Set the value given a native endian value. set(&mut self, e: E, n: i64)714 pub fn set(&mut self, e: E, n: i64) { 715 self.0 = e.write_i64_bytes(n); 716 } 717 } 718 719 impl<E: Endian> fmt::Debug for U16Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result720 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 721 write!(f, "U16({:x}, {:x})", self.0[0], self.0[1],) 722 } 723 } 724 725 impl<E: Endian> fmt::Debug for U32Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result726 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 727 write!( 728 f, 729 "U32({:x}, {:x}, {:x}, {:x})", 730 self.0[0], self.0[1], self.0[2], self.0[3], 731 ) 732 } 733 } 734 735 impl<E: Endian> fmt::Debug for U64Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result736 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 737 write!( 738 f, 739 "U64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})", 740 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7], 741 ) 742 } 743 } 744 745 impl<E: Endian> fmt::Debug for I16Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result746 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 747 write!(f, "I16({:x}, {:x})", self.0[0], self.0[1],) 748 } 749 } 750 751 impl<E: Endian> fmt::Debug for I32Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result752 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 753 write!( 754 f, 755 "I32({:x}, {:x}, {:x}, {:x})", 756 self.0[0], self.0[1], self.0[2], self.0[3], 757 ) 758 } 759 } 760 761 impl<E: Endian> fmt::Debug for I64Bytes<E> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result762 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 763 write!( 764 f, 765 "I64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})", 766 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7], 767 ) 768 } 769 } 770 771 unsafe_impl_endian_pod!(U16Bytes, U32Bytes, U64Bytes, I16Bytes, I32Bytes, I64Bytes); 772