1#[cfg(feature = "io-core")]
7pub mod core_io {
8 use crate::{BigEndian, LittleEndian, SpecificEndian};
9 use core::mem::size_of;
10
11 pub trait EndianRepr: Copy {
15 fn from_u128(v: u128) -> Self;
16 fn to_u128(self) -> u128;
17 }
18
19 impl EndianRepr for u8 {
20 fn from_u128(v: u128) -> Self {
21 v as u8
22 }
23 fn to_u128(self) -> u128 {
24 self as u128
25 }
26 }
27 impl EndianRepr for u16 {
28 fn from_u128(v: u128) -> Self {
29 v as u16
30 }
31 fn to_u128(self) -> u128 {
32 self as u128
33 }
34 }
35 impl EndianRepr for u32 {
36 fn from_u128(v: u128) -> Self {
37 v as u32
38 }
39 fn to_u128(self) -> u128 {
40 self as u128
41 }
42 }
43 impl EndianRepr for u64 {
44 fn from_u128(v: u128) -> Self {
45 v as u64
46 }
47 fn to_u128(self) -> u128 {
48 self as u128
49 }
50 }
51 impl EndianRepr for u128 {
52 fn from_u128(v: u128) -> Self {
53 v
54 }
55 fn to_u128(self) -> u128 {
56 self
57 }
58 }
59 impl EndianRepr for f32 {
60 fn from_u128(v: u128) -> Self {
61 f32::from_bits(v as u32)
62 }
63 fn to_u128(self) -> u128 {
64 self.to_bits() as u128
65 }
66 }
67 impl EndianRepr for f64 {
68 fn from_u128(v: u128) -> Self {
69 f64::from_bits(v as u64)
70 }
71 fn to_u128(self) -> u128 {
72 self.to_bits() as u128
73 }
74 }
75
76 macro_rules! impl_endianrepr_for_tuple {
94 ( $( ($idx:tt, $T:ident) ),+ $(,)? ) => {
95 impl<$( $T ),+> EndianRepr for ( $( $T ),+ )
96 where
97 $( $T: EndianRepr + Copy ),+
98 {
99 #[allow(unused_assignments)]
100 fn from_u128(v: u128) -> Self {
101 let bytes = v.to_be_bytes();
102 let total = 0usize $( + size_of::<$T>() )+;
103 if total > 16 {
104 panic!("tuple EndianRepr total size exceeds 16 bytes");
105 }
106 let mut offset = 16usize - total;
108 (
109 $(
110 {
111 let n = size_of::<$T>();
112 let chunk = &bytes[offset..offset + n];
113 let part = match n {
114 1 => chunk[0] as u128,
115 2 => u16::from_be_bytes([chunk[0], chunk[1]]) as u128,
116 4 => u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) as u128,
117 8 => u64::from_be_bytes([
118 chunk[0], chunk[1], chunk[2], chunk[3],
119 chunk[4], chunk[5], chunk[6], chunk[7],
120 ]) as u128,
121 16 => u128::from_be_bytes(chunk.try_into().unwrap()),
122 _ => panic!("unsupported size in tuple EndianRepr"),
123 };
124 offset += n;
125 <$T as EndianRepr>::from_u128(part)
126 }
127 ),+
128 )
129 }
130
131 #[allow(unused_assignments)]
132 fn to_u128(self) -> u128 {
133 let mut bytes = [0u8; 16];
134 let total = 0usize $( + size_of::<$T>() )+;
135 if total > 16 {
136 panic!("tuple EndianRepr total size exceeds 16 bytes");
137 }
138 let mut offset = 16usize - total;
141 $(
142 {
143 let n = size_of::<$T>();
144 let part = self.$idx.to_u128();
145 match n {
146 1 => bytes[offset] = part as u8,
147 2 => bytes[offset..offset + 2].copy_from_slice(&(part as u16).to_be_bytes()),
148 4 => bytes[offset..offset + 4].copy_from_slice(&(part as u32).to_be_bytes()),
149 8 => bytes[offset..offset + 8].copy_from_slice(&(part as u64).to_be_bytes()),
150 16 => bytes[offset..offset + 16].copy_from_slice(&(part as u128).to_be_bytes()),
151 _ => panic!("unsupported size in tuple EndianRepr"),
152 }
153 offset += n;
154 }
155 )+
156 u128::from_be_bytes(bytes)
157 }
158 }
159 };
160 }
161
162 impl_endianrepr_for_tuple!((0, A), (1, B));
163 impl_endianrepr_for_tuple!((0, A), (1, B), (2, C));
164 impl_endianrepr_for_tuple!((0, A), (1, B), (2, C), (3, D));
165 impl_endianrepr_for_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
166 impl_endianrepr_for_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
167 impl_endianrepr_for_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
168 impl_endianrepr_for_tuple!(
169 (0, A),
170 (1, B),
171 (2, C),
172 (3, D),
173 (4, E),
174 (5, F),
175 (6, G),
176 (7, H)
177 );
178 impl_endianrepr_for_tuple!(
179 (0, A),
180 (1, B),
181 (2, C),
182 (3, D),
183 (4, E),
184 (5, F),
185 (6, G),
186 (7, H),
187 (8, I)
188 );
189 impl_endianrepr_for_tuple!(
190 (0, A),
191 (1, B),
192 (2, C),
193 (3, D),
194 (4, E),
195 (5, F),
196 (6, G),
197 (7, H),
198 (8, I),
199 (9, J)
200 );
201 impl_endianrepr_for_tuple!(
202 (0, A),
203 (1, B),
204 (2, C),
205 (3, D),
206 (4, E),
207 (5, F),
208 (6, G),
209 (7, H),
210 (8, I),
211 (9, J),
212 (10, K)
213 );
214 impl_endianrepr_for_tuple!(
215 (0, A),
216 (1, B),
217 (2, C),
218 (3, D),
219 (4, E),
220 (5, F),
221 (6, G),
222 (7, H),
223 (8, I),
224 (9, J),
225 (10, K),
226 (11, L)
227 );
228
229 pub enum EndianValue<T>
250 where
251 T: crate::SpecificEndian<T>,
252 {
253 Big(BigEndian<T>),
254 Little(LittleEndian<T>),
255 }
256
257 impl<T> EndianValue<T>
258 where
259 T: crate::SpecificEndian<T> + Copy,
260 {
261 pub fn to_native(&self) -> T {
263 match self {
264 EndianValue::Big(b) => b.to_native(),
265 EndianValue::Little(l) => l.to_native(),
266 }
267 }
268 }
269
270 pub fn from_bytes<T>(data: &[u8]) -> Result<EndianValue<T>, &'static str>
273 where
274 T: crate::SpecificEndian<T> + Default + Copy + EndianRepr,
275 {
276 let default = T::default();
277 match default.endian() {
278 crate::Endian::Big => read_from_slice::<BigEndian<T>>(data).map(EndianValue::Big),
279 crate::Endian::Little => {
280 read_from_slice::<LittleEndian<T>>(data).map(EndianValue::Little)
281 }
282 }
283 }
284
285 pub fn from_bytes_to_native<T>(data: &[u8]) -> Result<T, &'static str>
287 where
288 T: crate::SpecificEndian<T> + Default + Copy + EndianRepr,
289 {
290 Ok(from_bytes::<T>(data)?.to_native())
291 }
292
293 pub trait FromSlice: Sized {
296 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str>;
297 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str>;
298 }
299
300 pub fn read_from_slice<E: FromSlice>(data: &[u8]) -> Result<E, &'static str> {
302 E::read_from_slice(data)
303 }
304
305 pub fn write_to_extend<E: FromSlice>(
306 v: &E,
307 out: &mut impl Extend<u8>,
308 ) -> Result<(), &'static str> {
309 v.write_to_extend(out)
310 }
311
312 impl<T> FromSlice for BigEndian<T>
313 where
314 T: SpecificEndian<T> + Copy + EndianRepr,
315 {
316 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
317 if data.len() < size_of::<T>() {
318 return Err("insufficient data");
319 }
320 let buf = &data[..size_of::<T>()];
321 let mut a = [0u8; 16];
324 a[16 - buf.len()..].copy_from_slice(buf);
325 let v = T::from_u128(u128::from_be_bytes(a));
326 Ok(BigEndian::from(v))
327 }
328
329 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
330 let repr = self.to_native().to_u128();
334 let bytes = repr.to_be_bytes();
335 let n = size_of::<T>();
336 if !(n == 1 || n == 2 || n == 4 || n == 8 || n == 16) {
337 return Err("unsupported size");
338 }
339 out.extend(core::iter::IntoIterator::into_iter(
341 bytes[16 - n..].iter().copied(),
342 ));
343 Ok(())
344 }
345 }
346
347 impl<T> FromSlice for LittleEndian<T>
348 where
349 T: SpecificEndian<T> + Copy + EndianRepr,
350 {
351 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
352 if data.len() < size_of::<T>() {
353 return Err("insufficient data");
354 }
355 let buf = &data[..size_of::<T>()];
356 let mut a = [0u8; 16];
358 a[..buf.len()].copy_from_slice(buf);
359 let v = T::from_u128(u128::from_le_bytes(a));
360 Ok(LittleEndian::from(v))
361 }
362
363 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
364 let repr = self.to_native().to_u128();
365 let bytes = repr.to_le_bytes();
366 let n = size_of::<T>();
367 if !(n == 1 || n == 2 || n == 4 || n == 8 || n == 16) {
368 return Err("unsupported size");
369 }
370 out.extend(core::iter::IntoIterator::into_iter(
371 bytes[..n].iter().copied(),
372 ));
373 Ok(())
374 }
375 }
376
377 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
380 impl<const N: usize> FromSlice for crate::FixedUtf16BeCodeUnits<N> {
381 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
382 if data.len() < 2 * N {
383 return Err("insufficient data");
384 }
385
386 let mut out = [crate::BigEndian::<u16>::from_bits(0); N];
387 let mut i = 0;
388 while i < N {
389 let base = 2 * i;
390 let native = u16::from_be_bytes([data[base], data[base + 1]]);
392 #[cfg(target_endian = "big")]
394 {
395 out[i] = crate::BigEndian::<u16>::from_bits(native);
396 }
397 #[cfg(target_endian = "little")]
398 {
399 out[i] = crate::BigEndian::<u16>::from_bits(native.swap_bytes());
400 }
401 i += 1;
402 }
403
404 Ok(crate::FixedUtf16BeCodeUnits::from(out))
405 }
406
407 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
408 for cu in self.as_units() {
409 out.extend(core::iter::IntoIterator::into_iter(
411 cu.to_native().to_be_bytes(),
412 ));
413 }
414 Ok(())
415 }
416 }
417
418 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
419 impl<const N: usize> FromSlice for crate::FixedUtf16LeCodeUnits<N> {
420 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
421 if data.len() < 2 * N {
422 return Err("insufficient data");
423 }
424
425 let mut out = [crate::LittleEndian::<u16>::from_bits(0); N];
426 let mut i = 0;
427 while i < N {
428 let base = 2 * i;
429 let native = u16::from_le_bytes([data[base], data[base + 1]]);
431 #[cfg(target_endian = "little")]
433 {
434 out[i] = crate::LittleEndian::<u16>::from_bits(native);
435 }
436 #[cfg(target_endian = "big")]
437 {
438 out[i] = crate::LittleEndian::<u16>::from_bits(native.swap_bytes());
439 }
440 i += 1;
441 }
442
443 Ok(crate::FixedUtf16LeCodeUnits::from(out))
444 }
445
446 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
447 for cu in self.as_units() {
448 out.extend(core::iter::IntoIterator::into_iter(
450 cu.to_native().to_le_bytes(),
451 ));
452 }
453 Ok(())
454 }
455 }
456
457 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
458 impl<const N: usize> FromSlice for crate::FixedUtf32BeCodeUnits<N> {
459 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
460 if data.len() < 4 * N {
461 return Err("insufficient data");
462 }
463
464 let mut out = [crate::BigEndian::<u32>::from_bits(0); N];
465 let mut i = 0;
466 while i < N {
467 let base = 4 * i;
468 let native = u32::from_be_bytes([
470 data[base],
471 data[base + 1],
472 data[base + 2],
473 data[base + 3],
474 ]);
475 #[cfg(target_endian = "big")]
477 {
478 out[i] = crate::BigEndian::<u32>::from_bits(native);
479 }
480 #[cfg(target_endian = "little")]
481 {
482 out[i] = crate::BigEndian::<u32>::from_bits(native.swap_bytes());
483 }
484 i += 1;
485 }
486
487 Ok(crate::FixedUtf32BeCodeUnits::from(out))
488 }
489
490 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
491 for cu in self.as_units() {
492 out.extend(core::iter::IntoIterator::into_iter(
494 cu.to_native().to_be_bytes(),
495 ));
496 }
497 Ok(())
498 }
499 }
500
501 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
502 impl<const N: usize> FromSlice for crate::FixedUtf32LeCodeUnits<N> {
503 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
504 if data.len() < 4 * N {
505 return Err("insufficient data");
506 }
507
508 let mut out = [crate::LittleEndian::<u32>::from_bits(0); N];
509 let mut i = 0;
510 while i < N {
511 let base = 4 * i;
512 let native = u32::from_le_bytes([
514 data[base],
515 data[base + 1],
516 data[base + 2],
517 data[base + 3],
518 ]);
519 #[cfg(target_endian = "little")]
521 {
522 out[i] = crate::LittleEndian::<u32>::from_bits(native);
523 }
524 #[cfg(target_endian = "big")]
525 {
526 out[i] = crate::LittleEndian::<u32>::from_bits(native.swap_bytes());
527 }
528 i += 1;
529 }
530
531 Ok(crate::FixedUtf32LeCodeUnits::from(out))
532 }
533
534 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
535 for cu in self.as_units() {
536 out.extend(core::iter::IntoIterator::into_iter(
538 cu.to_native().to_le_bytes(),
539 ));
540 }
541 Ok(())
542 }
543 }
544
545 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
546 impl<const N: usize> FromSlice for crate::FixedUtf16BeNullPadded<N> {
547 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
548 Ok(crate::FixedUtf16BeNullPadded::from(
549 <crate::FixedUtf16BeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
550 ))
551 }
552
553 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
554 <crate::FixedUtf16BeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
555 }
556 }
557
558 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
559 impl<const N: usize> FromSlice for crate::FixedUtf16BeSpacePadded<N> {
560 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
561 Ok(crate::FixedUtf16BeSpacePadded::from(
562 <crate::FixedUtf16BeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
563 ))
564 }
565
566 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
567 <crate::FixedUtf16BeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
568 }
569 }
570
571 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
572 impl<const N: usize> FromSlice for crate::FixedUtf16LeNullPadded<N> {
573 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
574 Ok(crate::FixedUtf16LeNullPadded::from(
575 <crate::FixedUtf16LeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
576 ))
577 }
578
579 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
580 <crate::FixedUtf16LeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
581 }
582 }
583
584 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
585 impl<const N: usize> FromSlice for crate::FixedUtf16LeSpacePadded<N> {
586 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
587 Ok(crate::FixedUtf16LeSpacePadded::from(
588 <crate::FixedUtf16LeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
589 ))
590 }
591
592 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
593 <crate::FixedUtf16LeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
594 }
595 }
596
597 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
598 impl<const N: usize> FromSlice for crate::FixedUtf32BeNullPadded<N> {
599 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
600 Ok(crate::FixedUtf32BeNullPadded::from(
601 <crate::FixedUtf32BeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
602 ))
603 }
604
605 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
606 <crate::FixedUtf32BeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
607 }
608 }
609
610 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
611 impl<const N: usize> FromSlice for crate::FixedUtf32BeSpacePadded<N> {
612 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
613 Ok(crate::FixedUtf32BeSpacePadded::from(
614 <crate::FixedUtf32BeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
615 ))
616 }
617
618 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
619 <crate::FixedUtf32BeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
620 }
621 }
622
623 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
624 impl<const N: usize> FromSlice for crate::FixedUtf32LeNullPadded<N> {
625 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
626 Ok(crate::FixedUtf32LeNullPadded::from(
627 <crate::FixedUtf32LeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
628 ))
629 }
630
631 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
632 <crate::FixedUtf32LeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
633 }
634 }
635
636 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
637 impl<const N: usize> FromSlice for crate::FixedUtf32LeSpacePadded<N> {
638 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
639 Ok(crate::FixedUtf32LeSpacePadded::from(
640 <crate::FixedUtf32LeCodeUnits<N> as FromSlice>::read_from_slice(data)?,
641 ))
642 }
643
644 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
645 <crate::FixedUtf32LeCodeUnits<N> as FromSlice>::write_to_extend(&self.0, out)
646 }
647 }
648
649 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
650 impl<const N: usize> FromSlice for crate::FixedUtf8NullPadded<N> {
651 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
652 if data.len() < N {
653 return Err("insufficient data");
654 }
655 let mut out = [0u8; N];
656 out.copy_from_slice(&data[..N]);
657 Ok(crate::FixedUtf8NullPadded::from(
658 crate::FixedUtf8Bytes::from(out),
659 ))
660 }
661
662 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
663 out.extend(self.0.as_bytes().iter().copied());
664 Ok(())
665 }
666 }
667
668 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
669 impl<const N: usize> FromSlice for crate::FixedUtf8SpacePadded<N> {
670 fn read_from_slice(data: &[u8]) -> Result<Self, &'static str> {
671 if data.len() < N {
672 return Err("insufficient data");
673 }
674 let mut out = [0u8; N];
675 out.copy_from_slice(&data[..N]);
676 Ok(crate::FixedUtf8SpacePadded::from(
677 crate::FixedUtf8Bytes::from(out),
678 ))
679 }
680
681 fn write_to_extend(&self, out: &mut impl Extend<u8>) -> Result<(), &'static str> {
682 out.extend(self.0.as_bytes().iter().copied());
683 Ok(())
684 }
685 }
686}
687
688#[cfg(feature = "io-std")]
690pub mod std_io {
691 use super::core_io;
692 use crate::{BigEndian, LittleEndian};
693 use core::any::TypeId;
694 use core::mem::size_of;
695 use std::io::{self, Read, Write};
696
697 fn read_be<R, T>(reader: &mut R) -> io::Result<BigEndian<T>>
698 where
699 R: Read + ?Sized,
700 T: crate::SpecificEndian<T> + Default + Copy + core_io::EndianRepr + 'static,
701 {
702 if TypeId::of::<T>() == TypeId::of::<u16>() {
704 let mut buf = [0u8; 2];
705 reader.read_exact(&mut buf)?;
706 let v = u16::from_be_bytes(buf);
707 let v: T = unsafe { core::mem::transmute_copy(&v) };
709 return Ok(BigEndian::from(v));
710 }
711 if TypeId::of::<T>() == TypeId::of::<u32>() {
712 let mut buf = [0u8; 4];
713 reader.read_exact(&mut buf)?;
714 let v = u32::from_be_bytes(buf);
715 let v: T = unsafe { core::mem::transmute_copy(&v) };
716 return Ok(BigEndian::from(v));
717 }
718 if TypeId::of::<T>() == TypeId::of::<u64>() {
719 let mut buf = [0u8; 8];
720 reader.read_exact(&mut buf)?;
721 let v = u64::from_be_bytes(buf);
722 let v: T = unsafe { core::mem::transmute_copy(&v) };
723 return Ok(BigEndian::from(v));
724 }
725
726 let mut buf = vec![0u8; size_of::<T>()];
727 reader.read_exact(&mut buf)?;
728 core_io::read_from_slice::<BigEndian<T>>(&buf)
729 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
730 }
731
732 fn read_le<R, T>(reader: &mut R) -> io::Result<LittleEndian<T>>
733 where
734 R: Read + ?Sized,
735 T: crate::SpecificEndian<T> + Default + Copy + core_io::EndianRepr + 'static,
736 {
737 if TypeId::of::<T>() == TypeId::of::<u16>() {
738 let mut buf = [0u8; 2];
739 reader.read_exact(&mut buf)?;
740 let v = u16::from_le_bytes(buf);
741 let v: T = unsafe { core::mem::transmute_copy(&v) };
742 return Ok(LittleEndian::from(v));
743 }
744 if TypeId::of::<T>() == TypeId::of::<u32>() {
745 let mut buf = [0u8; 4];
746 reader.read_exact(&mut buf)?;
747 let v = u32::from_le_bytes(buf);
748 let v: T = unsafe { core::mem::transmute_copy(&v) };
749 return Ok(LittleEndian::from(v));
750 }
751 if TypeId::of::<T>() == TypeId::of::<u64>() {
752 let mut buf = [0u8; 8];
753 reader.read_exact(&mut buf)?;
754 let v = u64::from_le_bytes(buf);
755 let v: T = unsafe { core::mem::transmute_copy(&v) };
756 return Ok(LittleEndian::from(v));
757 }
758
759 let mut buf = vec![0u8; size_of::<T>()];
760 reader.read_exact(&mut buf)?;
761 core_io::read_from_slice::<LittleEndian<T>>(&buf)
762 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
763 }
764
765 fn write_be<W, T>(writer: &mut W, v: &BigEndian<T>) -> io::Result<()>
766 where
767 W: Write + ?Sized,
768 T: crate::SpecificEndian<T> + Copy + core_io::EndianRepr + 'static,
769 {
770 if TypeId::of::<T>() == TypeId::of::<u16>() {
771 let n: u16 = unsafe { core::mem::transmute_copy(&v.to_native()) };
772 return writer.write_all(&n.to_be_bytes());
773 }
774 if TypeId::of::<T>() == TypeId::of::<u32>() {
775 let n: u32 = unsafe { core::mem::transmute_copy(&v.to_native()) };
776 return writer.write_all(&n.to_be_bytes());
777 }
778 if TypeId::of::<T>() == TypeId::of::<u64>() {
779 let n: u64 = unsafe { core::mem::transmute_copy(&v.to_native()) };
780 return writer.write_all(&n.to_be_bytes());
781 }
782
783 let mut out = Vec::new();
784 core_io::write_to_extend(v, &mut out)
785 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
786 writer.write_all(&out)
787 }
788
789 fn write_le<W, T>(writer: &mut W, v: &LittleEndian<T>) -> io::Result<()>
790 where
791 W: Write + ?Sized,
792 T: crate::SpecificEndian<T> + Copy + core_io::EndianRepr + 'static,
793 {
794 if TypeId::of::<T>() == TypeId::of::<u16>() {
795 let n: u16 = unsafe { core::mem::transmute_copy(&v.to_native()) };
796 return writer.write_all(&n.to_le_bytes());
797 }
798 if TypeId::of::<T>() == TypeId::of::<u32>() {
799 let n: u32 = unsafe { core::mem::transmute_copy(&v.to_native()) };
800 return writer.write_all(&n.to_le_bytes());
801 }
802 if TypeId::of::<T>() == TypeId::of::<u64>() {
803 let n: u64 = unsafe { core::mem::transmute_copy(&v.to_native()) };
804 return writer.write_all(&n.to_le_bytes());
805 }
806
807 let mut out = Vec::new();
808 core_io::write_to_extend(v, &mut out)
809 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
810 writer.write_all(&out)
811 }
812
813 pub trait EndianRead: Sized {
814 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self>;
815 }
816
817 pub trait EndianWrite {
818 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()>;
819 }
820
821 impl<T> EndianRead for BigEndian<T>
822 where
823 T: crate::SpecificEndian<T> + Default + Copy + core_io::EndianRepr + 'static,
824 {
825 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
826 read_be::<R, T>(reader)
827 }
828 }
829
830 impl<T> EndianRead for LittleEndian<T>
831 where
832 T: crate::SpecificEndian<T> + Default + Copy + core_io::EndianRepr + 'static,
833 {
834 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
835 read_le::<R, T>(reader)
836 }
837 }
838
839 impl<T> EndianWrite for BigEndian<T>
840 where
841 T: crate::SpecificEndian<T> + Copy + core_io::EndianRepr + 'static,
842 {
843 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
844 write_be::<W, T>(writer, self)
845 }
846 }
847
848 impl<T> EndianWrite for LittleEndian<T>
849 where
850 T: crate::SpecificEndian<T> + Copy + core_io::EndianRepr + 'static,
851 {
852 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
853 write_le::<W, T>(writer, self)
854 }
855 }
856
857 impl<const N: usize> EndianRead for [u8; N] {
866 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
867 let mut buf = [0u8; N];
868 reader.read_exact(&mut buf)?;
869 Ok(buf)
870 }
871 }
872
873 impl<const N: usize> EndianWrite for [u8; N] {
874 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
875 writer.write_all(self)
876 }
877 }
878
879 impl<E, const N: usize> EndianRead for [E; N]
880 where
881 E: EndianRead + Copy,
882 {
883 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
884 let mut out = [E::read_from(reader)?; N];
885 for i in 1..N {
886 out[i] = E::read_from(reader)?;
887 }
888 Ok(out)
889 }
890 }
891
892 impl<E, const N: usize> EndianWrite for [E; N]
893 where
894 E: EndianWrite,
895 {
896 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
897 for v in self {
898 v.write_to(writer)?;
899 }
900 Ok(())
901 }
902 }
903
904 pub fn read_specific<R, E>(reader: &mut R) -> io::Result<E>
930 where
931 R: Read + ?Sized,
932 E: EndianRead,
933 {
934 E::read_from(reader)
935 }
936
937 pub fn write_specific<W, E>(writer: &mut W, v: &E) -> io::Result<()>
941 where
942 W: Write + ?Sized,
943 E: EndianWrite,
944 {
945 v.write_to(writer)
946 }
947
948 pub fn read_specific_dyn<E>(reader: &mut dyn Read) -> io::Result<E>
954 where
955 E: EndianRead,
956 {
957 read_specific::<dyn Read, E>(reader)
958 }
959
960 pub fn write_specific_dyn<E>(writer: &mut dyn Write, v: &E) -> io::Result<()>
966 where
967 E: EndianWrite,
968 {
969 write_specific::<dyn Write, E>(writer, v)
970 }
971
972 pub fn read_native<R, W, T>(reader: &mut R) -> io::Result<T>
1016 where
1017 R: Read + ?Sized,
1018 W: EndianRead,
1019 T: From<W>,
1020 {
1021 let wire: W = read_specific(reader)?;
1022 Ok(wire.into())
1023 }
1024
1025 pub fn try_read_native<R, W, T>(reader: &mut R) -> io::Result<T>
1029 where
1030 R: Read + ?Sized,
1031 W: EndianRead,
1032 T: TryFrom<W>,
1033 <T as TryFrom<W>>::Error: core::fmt::Display,
1034 {
1035 let wire: W = read_specific(reader)?;
1036 T::try_from(wire).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))
1037 }
1038
1039 pub fn write_native<Wrt, W, T>(writer: &mut Wrt, v: T) -> io::Result<()>
1050 where
1051 Wrt: Write + ?Sized,
1052 W: EndianWrite,
1053 W: From<T>,
1054 {
1055 let wire: W = v.into();
1056 write_specific(writer, &wire)
1057 }
1058
1059 pub fn write_native_ref<Wrt, W, T>(writer: &mut Wrt, v: &T) -> io::Result<()>
1063 where
1064 Wrt: Write + ?Sized,
1065 W: EndianWrite,
1066 T: Clone,
1067 W: From<T>,
1068 {
1069 write_native::<Wrt, W, T>(writer, v.clone())
1070 }
1071
1072 pub fn try_write_native<Wrt, W, T>(writer: &mut Wrt, v: T) -> io::Result<()>
1076 where
1077 Wrt: Write + ?Sized,
1078 W: EndianWrite,
1079 W: TryFrom<T>,
1080 <W as TryFrom<T>>::Error: core::fmt::Display,
1081 {
1082 let wire: W = W::try_from(v)
1083 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))?;
1084 write_specific(writer, &wire)
1085 }
1086
1087 pub fn try_write_native_ref<Wrt, W, T>(writer: &mut Wrt, v: &T) -> io::Result<()>
1091 where
1092 Wrt: Write + ?Sized,
1093 W: EndianWrite,
1094 T: Clone,
1095 W: TryFrom<T>,
1096 <W as TryFrom<T>>::Error: core::fmt::Display,
1097 {
1098 try_write_native::<Wrt, W, T>(writer, v.clone())
1099 }
1100
1101 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1104 impl<const N: usize> EndianRead for crate::FixedUtf16BeCodeUnits<N> {
1105 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1106 let mut buf = vec![0u8; 2 * N];
1107 reader.read_exact(&mut buf)?;
1108 core_io::read_from_slice::<Self>(&buf)
1109 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1110 }
1111 }
1112
1113 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1114 impl<const N: usize> EndianRead for crate::FixedUtf16BeNullPadded<N> {
1115 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1116 let mut buf = vec![0u8; 2 * N];
1117 reader.read_exact(&mut buf)?;
1118 core_io::read_from_slice::<Self>(&buf)
1119 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1120 }
1121 }
1122
1123 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1124 impl<const N: usize> EndianWrite for crate::FixedUtf16BeNullPadded<N> {
1125 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1126 let mut out = Vec::new();
1127 core_io::write_to_extend(self, &mut out)
1128 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1129 writer.write_all(&out)
1130 }
1131 }
1132
1133 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1134 impl<const N: usize> EndianRead for crate::FixedUtf16BeSpacePadded<N> {
1135 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1136 let mut buf = vec![0u8; 2 * N];
1137 reader.read_exact(&mut buf)?;
1138 core_io::read_from_slice::<Self>(&buf)
1139 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1140 }
1141 }
1142
1143 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1144 impl<const N: usize> EndianWrite for crate::FixedUtf16BeSpacePadded<N> {
1145 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1146 let mut out = Vec::new();
1147 core_io::write_to_extend(self, &mut out)
1148 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1149 writer.write_all(&out)
1150 }
1151 }
1152
1153 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1154 impl<const N: usize> EndianWrite for crate::FixedUtf16BeCodeUnits<N> {
1155 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1156 let mut out = Vec::new();
1157 core_io::write_to_extend(self, &mut out)
1158 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1159 writer.write_all(&out)
1160 }
1161 }
1162
1163 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1164 impl<const N: usize> EndianRead for crate::FixedUtf16LeCodeUnits<N> {
1165 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1166 let mut buf = vec![0u8; 2 * N];
1167 reader.read_exact(&mut buf)?;
1168 core_io::read_from_slice::<Self>(&buf)
1169 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1170 }
1171 }
1172
1173 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1174 impl<const N: usize> EndianRead for crate::FixedUtf16LeNullPadded<N> {
1175 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1176 let mut buf = vec![0u8; 2 * N];
1177 reader.read_exact(&mut buf)?;
1178 core_io::read_from_slice::<Self>(&buf)
1179 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1180 }
1181 }
1182
1183 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1184 impl<const N: usize> EndianWrite for crate::FixedUtf16LeNullPadded<N> {
1185 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1186 let mut out = Vec::new();
1187 core_io::write_to_extend(self, &mut out)
1188 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1189 writer.write_all(&out)
1190 }
1191 }
1192
1193 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1194 impl<const N: usize> EndianRead for crate::FixedUtf16LeSpacePadded<N> {
1195 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1196 let mut buf = vec![0u8; 2 * N];
1197 reader.read_exact(&mut buf)?;
1198 core_io::read_from_slice::<Self>(&buf)
1199 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1200 }
1201 }
1202
1203 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1204 impl<const N: usize> EndianWrite for crate::FixedUtf16LeSpacePadded<N> {
1205 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1206 let mut out = Vec::new();
1207 core_io::write_to_extend(self, &mut out)
1208 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1209 writer.write_all(&out)
1210 }
1211 }
1212
1213 #[cfg(all(feature = "text_fixed", feature = "text_utf16"))]
1214 impl<const N: usize> EndianWrite for crate::FixedUtf16LeCodeUnits<N> {
1215 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1216 let mut out = Vec::new();
1217 core_io::write_to_extend(self, &mut out)
1218 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1219 writer.write_all(&out)
1220 }
1221 }
1222
1223 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1224 impl<const N: usize> EndianRead for crate::FixedUtf32BeCodeUnits<N> {
1225 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1226 let mut buf = vec![0u8; 4 * N];
1227 reader.read_exact(&mut buf)?;
1228 core_io::read_from_slice::<Self>(&buf)
1229 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1230 }
1231 }
1232
1233 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1234 impl<const N: usize> EndianRead for crate::FixedUtf32BeNullPadded<N> {
1235 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1236 let mut buf = vec![0u8; 4 * N];
1237 reader.read_exact(&mut buf)?;
1238 core_io::read_from_slice::<Self>(&buf)
1239 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1240 }
1241 }
1242
1243 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1244 impl<const N: usize> EndianWrite for crate::FixedUtf32BeNullPadded<N> {
1245 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1246 let mut out = Vec::new();
1247 core_io::write_to_extend(self, &mut out)
1248 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1249 writer.write_all(&out)
1250 }
1251 }
1252
1253 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1254 impl<const N: usize> EndianRead for crate::FixedUtf32BeSpacePadded<N> {
1255 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1256 let mut buf = vec![0u8; 4 * N];
1257 reader.read_exact(&mut buf)?;
1258 core_io::read_from_slice::<Self>(&buf)
1259 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1260 }
1261 }
1262
1263 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1264 impl<const N: usize> EndianWrite for crate::FixedUtf32BeSpacePadded<N> {
1265 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1266 let mut out = Vec::new();
1267 core_io::write_to_extend(self, &mut out)
1268 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1269 writer.write_all(&out)
1270 }
1271 }
1272
1273 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1274 impl<const N: usize> EndianWrite for crate::FixedUtf32BeCodeUnits<N> {
1275 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1276 let mut out = Vec::new();
1277 core_io::write_to_extend(self, &mut out)
1278 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1279 writer.write_all(&out)
1280 }
1281 }
1282
1283 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1284 impl<const N: usize> EndianRead for crate::FixedUtf32LeCodeUnits<N> {
1285 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1286 let mut buf = vec![0u8; 4 * N];
1287 reader.read_exact(&mut buf)?;
1288 core_io::read_from_slice::<Self>(&buf)
1289 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1290 }
1291 }
1292
1293 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1294 impl<const N: usize> EndianRead for crate::FixedUtf32LeNullPadded<N> {
1295 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1296 let mut buf = vec![0u8; 4 * N];
1297 reader.read_exact(&mut buf)?;
1298 core_io::read_from_slice::<Self>(&buf)
1299 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1300 }
1301 }
1302
1303 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1304 impl<const N: usize> EndianWrite for crate::FixedUtf32LeNullPadded<N> {
1305 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1306 let mut out = Vec::new();
1307 core_io::write_to_extend(self, &mut out)
1308 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1309 writer.write_all(&out)
1310 }
1311 }
1312
1313 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1314 impl<const N: usize> EndianRead for crate::FixedUtf32LeSpacePadded<N> {
1315 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1316 let mut buf = vec![0u8; 4 * N];
1317 reader.read_exact(&mut buf)?;
1318 core_io::read_from_slice::<Self>(&buf)
1319 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1320 }
1321 }
1322
1323 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1324 impl<const N: usize> EndianWrite for crate::FixedUtf32LeSpacePadded<N> {
1325 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1326 let mut out = Vec::new();
1327 core_io::write_to_extend(self, &mut out)
1328 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1329 writer.write_all(&out)
1330 }
1331 }
1332
1333 #[cfg(all(feature = "text_fixed", feature = "text_utf32"))]
1334 impl<const N: usize> EndianWrite for crate::FixedUtf32LeCodeUnits<N> {
1335 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1336 let mut out = Vec::new();
1337 core_io::write_to_extend(self, &mut out)
1338 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1339 writer.write_all(&out)
1340 }
1341 }
1342
1343 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
1346 impl<const N: usize> EndianRead for crate::FixedUtf8NullPadded<N> {
1347 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1348 let mut buf = vec![0u8; N];
1349 reader.read_exact(&mut buf)?;
1350 core_io::read_from_slice::<Self>(&buf)
1351 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1352 }
1353 }
1354
1355 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
1356 impl<const N: usize> EndianWrite for crate::FixedUtf8NullPadded<N> {
1357 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1358 let mut out = Vec::new();
1359 core_io::write_to_extend(self, &mut out)
1360 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1361 writer.write_all(&out)
1362 }
1363 }
1364
1365 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
1366 impl<const N: usize> EndianRead for crate::FixedUtf8SpacePadded<N> {
1367 fn read_from<R: Read + ?Sized>(reader: &mut R) -> io::Result<Self> {
1368 let mut buf = vec![0u8; N];
1369 reader.read_exact(&mut buf)?;
1370 core_io::read_from_slice::<Self>(&buf)
1371 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
1372 }
1373 }
1374
1375 #[cfg(all(feature = "text_fixed", feature = "text_utf8"))]
1376 impl<const N: usize> EndianWrite for crate::FixedUtf8SpacePadded<N> {
1377 fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
1378 let mut out = Vec::new();
1379 core_io::write_to_extend(self, &mut out)
1380 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
1381 writer.write_all(&out)
1382 }
1383 }
1384}
1385
1386#[cfg(all(test, feature = "io-std"))]
1387mod tests {
1388 use super::std_io::*;
1389 use crate::{BigEndian, LittleEndian, SpecificEndian};
1390 use std::io::Cursor;
1391
1392 fn round_trip_be<T>(val: T)
1393 where
1394 T: SpecificEndian<T> + Copy + PartialEq + core::fmt::Debug,
1395 BigEndian<T>: EndianWrite + EndianRead + From<T> + Into<T>,
1396 {
1397 let be: BigEndian<T> = BigEndian::from(val);
1398 let mut buf = Vec::new();
1399 write_specific(&mut buf, &be).unwrap();
1400
1401 let mut cur = Cursor::new(buf);
1402 let out: BigEndian<T> = read_specific(&mut cur).unwrap();
1403 assert_eq!(out.to_native(), be.to_native());
1404 }
1405
1406 fn round_trip_le<T>(val: T)
1407 where
1408 T: SpecificEndian<T> + Copy + PartialEq + core::fmt::Debug,
1409 LittleEndian<T>: EndianWrite + EndianRead + From<T> + Into<T>,
1410 {
1411 let le: LittleEndian<T> = LittleEndian::from(val);
1412 let mut buf = Vec::new();
1413 write_specific(&mut buf, &le).unwrap();
1414
1415 let mut cur = Cursor::new(buf);
1416 let out: LittleEndian<T> = read_specific(&mut cur).unwrap();
1417 assert_eq!(out.to_native(), le.to_native());
1418 }
1419
1420 #[test]
1421 fn be_u16_round_trip() {
1422 round_trip_be::<u16>(0x1234);
1423 }
1424
1425 #[test]
1426 fn le_u16_round_trip() {
1427 round_trip_le::<u16>(0x1234);
1428 }
1429
1430 #[test]
1431 fn be_u32_round_trip() {
1432 round_trip_be::<u32>(0x12345678);
1433 }
1434
1435 #[test]
1436 fn le_u32_round_trip() {
1437 round_trip_le::<u32>(0x12345678);
1438 }
1439
1440 #[test]
1441 fn be_u64_round_trip() {
1442 round_trip_be::<u64>(0x1234567890abcdef);
1443 }
1444
1445 #[test]
1446 fn le_u64_round_trip() {
1447 round_trip_le::<u64>(0x1234567890abcdef);
1448 }
1449
1450 #[test]
1451 fn be_f32_round_trip() {
1452 round_trip_be::<f32>(1234.5);
1453 }
1454
1455 #[test]
1456 fn le_f32_round_trip() {
1457 round_trip_le::<f32>(1234.5);
1458 }
1459
1460 #[test]
1461 fn be_f64_round_trip() {
1462 round_trip_be::<f64>(1234567.89);
1463 }
1464
1465 #[test]
1466 fn le_f64_round_trip() {
1467 round_trip_le::<f64>(1234567.89);
1468 }
1469
1470 #[test]
1471 fn multiple_sequence_read() {
1472 let a: BigEndian<u16> = 0xfaceu16.into();
1474 let b: LittleEndian<u32> = 0xdeadbeefu32.into();
1475 let c: BigEndian<u8> = 0x7fu8.into();
1476
1477 let mut buf = Vec::new();
1478 write_specific(&mut buf, &a).unwrap();
1479 write_specific(&mut buf, &b).unwrap();
1480 write_specific(&mut buf, &c).unwrap();
1481
1482 let mut cur = Cursor::new(buf);
1483 let ra: BigEndian<u16> = read_specific(&mut cur).unwrap();
1484 let rb: LittleEndian<u32> = read_specific(&mut cur).unwrap();
1485 let rc: BigEndian<u8> = read_specific(&mut cur).unwrap();
1486
1487 assert_eq!(ra.to_native(), a.to_native());
1488 assert_eq!(rb.to_native(), b.to_native());
1489 assert_eq!(rc.to_native(), c.to_native());
1490 }
1491
1492 #[test]
1493 fn insufficient_bytes_error() {
1494 let mut cur = Cursor::new(vec![0u8; 3]);
1496 let res: std::io::Result<BigEndian<u64>> = read_specific(&mut cur);
1497 assert!(res.is_err());
1498 }
1499}