ttf_view/types/
big_endian.rs1use crate::types::{
2 Affine2x2, F2Dot14, Fixed, LongDateTime, Version16Dot16, int16, int32, int64, u24, uint16,
3 uint32, uint64,
4};
5
6mod private {
7 pub trait Sealed {}
8}
9
10pub const trait Primitive: private::Sealed + Copy {
11 type BigEndian: Copy;
12 fn from_big_endian(be: Self::BigEndian) -> Self;
13 fn to_big_endian(ne: Self) -> Self::BigEndian;
14}
15
16macro_rules! impl_primitives {
17 ($( $ne_ty:ty, $be_ty:ty, |$be:ident| $from_be:expr, |$ne:ident| $to_be:expr ; )*) => ($(
18 impl private::Sealed for $ne_ty {}
19 const impl Primitive for $ne_ty {
20 type BigEndian = $be_ty;
21 fn from_big_endian($be: Self::BigEndian) -> Self { $from_be }
22 fn to_big_endian($ne: Self) -> Self::BigEndian { $to_be }
23 }
24 const impl From<BigEndian<$ne_ty>> for $ne_ty {
25 fn from(value: BigEndian<$ne_ty>) -> Self {
26 value.get()
27 }
28 }
29 )*);
30}
31impl_primitives! {
32 i16, int16, |x| x.get(), |x| int16::new(x);
34 i32, int32, |x| x.get(), |x| int32::new(x);
35 i64, int64, |x| x.get(), |x| int64::new(x);
36 u16, uint16, |x| x.get(), |x| uint16::new(x);
37 u32, uint32, |x| x.get(), |x| uint32::new(x);
38 u64, uint64, |x| x.get(), |x| uint64::new(x);
39
40 Fixed, [u8; 4], |x| Fixed::from_be_bytes(x), |x| x.to_be_bytes();
41 F2Dot14, [u8; 2], |x| F2Dot14::from_be_bytes(x), |x| x.to_be_bytes();
42 LongDateTime, [u8; 8], |x| LongDateTime::from_be_bytes(x), |x| x.to_be_bytes();
43 u24, [u8; 3], |x| u24::from_be_bytes(x), |x| x.to_be_bytes();
44 Version16Dot16, [u8; 4], |x| unsafe { Version16Dot16::from_be_bytes_unchecked(x) },
45 |x| x.to_be_bytes();
46 Affine2x2, [u8; 8], |x| Affine2x2::from_be_bytes(x), |x| x.to_be_bytes();
47}
48
49#[derive(Copy)]
50#[derive_const(Clone, Default, PartialEq, Eq)]
51#[repr(transparent)]
52pub struct BigEndian<T: Primitive>(T::BigEndian);
53
54impl<T: Primitive> BigEndian<T> {
55 pub const fn new(value: T) -> Self
56 where T: [const] Primitive {
57 Self(T::to_big_endian(value))
58 }
59 pub const fn get(self) -> T
60 where T: [const] Primitive {
61 T::from_big_endian(self.0)
62 }
63}
64
65const impl<T: [const] Primitive> From<T> for BigEndian<T> {
66 fn from(value: T) -> Self {
67 Self::new(value)
68 }
69}
70
71macro_rules! impl_extra_traits_for_big_endian {
73 ($($ty:ty),* $(,)?) => ($(
74 impl std::ops::Deref for BigEndian<$ty> {
75 type Target = <$ty as Primitive>::BigEndian;
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79 }
80 const impl From<BigEndian<$ty>> for <$ty as Primitive>::BigEndian {
81 fn from(value: BigEndian<$ty>) -> Self {
82 value.0
83 }
84 }
85 const impl From<<$ty as Primitive>::BigEndian> for BigEndian<$ty> {
86 fn from(value: <$ty as Primitive>::BigEndian) -> Self {
87 Self(value)
88 }
89 }
90 )*);
91}
92impl_extra_traits_for_big_endian! {
93 i16, i32, i64, u16, u32, u64,
94}
95
96macro_rules! impl_fmt_for_big_endian {
97 ($($Trait:ident),* $(,)?) => ($(
98 impl<T: Primitive + std::fmt::$Trait> std::fmt::$Trait for BigEndian<T> {
99 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
100 self.get().fmt(f)
101 }
102 }
103 )*);
104}
105impl_fmt_for_big_endian! { Debug, Display, Binary, Octal, LowerHex, UpperHex, LowerExp, UpperExp }