write_fonts/
offsets.rs

1//! compile-time representations of offsets
2
3use super::write::{FontWrite, TableWriter};
4
5/// The width in bytes of an Offset16
6#[allow(dead_code)] // currently unused because of a serde bug?
7                    // https://github.com/serde-rs/serde/issues/2449
8pub const WIDTH_16: usize = 2;
9/// The width in bytes of an Offset24
10#[allow(dead_code)] // will be used one day :')
11pub const WIDTH_24: usize = 3;
12/// The width in bytes of an Offset32
13pub const WIDTH_32: usize = 4;
14
15/// An offset subtable.
16///
17/// The generic const `N` is the width of the offset, in bytes.
18#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct OffsetMarker<T, const N: usize = 2> {
21    obj: Box<T>,
22}
23
24/// An offset subtable which may be null.
25///
26/// The generic const `N` is the width of the offset, in bytes.
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct NullableOffsetMarker<T, const N: usize = 2> {
30    obj: Option<Box<T>>,
31}
32
33impl<T, const N: usize> std::ops::Deref for OffsetMarker<T, N> {
34    type Target = T;
35    fn deref(&self) -> &Self::Target {
36        &self.obj
37    }
38}
39
40impl<T, const N: usize> std::ops::DerefMut for OffsetMarker<T, N> {
41    fn deref_mut(&mut self) -> &mut Self::Target {
42        &mut self.obj
43    }
44}
45
46impl<T, const N: usize> std::ops::Deref for NullableOffsetMarker<T, N> {
47    type Target = Option<Box<T>>;
48    fn deref(&self) -> &Self::Target {
49        &self.obj
50    }
51}
52
53impl<T, const N: usize> std::ops::DerefMut for NullableOffsetMarker<T, N> {
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.obj
56    }
57}
58
59impl<T, const N: usize> AsRef<T> for OffsetMarker<T, N> {
60    fn as_ref(&self) -> &T {
61        &self.obj
62    }
63}
64
65impl<T, const N: usize> AsMut<T> for OffsetMarker<T, N> {
66    fn as_mut(&mut self) -> &mut T {
67        &mut self.obj
68    }
69}
70
71// NOTE: we don't impl AsRef/AsMut for NullableOffsetMarker, since it is less
72// useful than the Option::as_ref and Option::as_mut methods available through deref
73
74impl<const N: usize, T> OffsetMarker<T, N> {
75    /// Create a new marker.
76    pub fn new(obj: T) -> Self {
77        OffsetMarker { obj: Box::new(obj) }
78    }
79
80    /// Set the contents of the marker, replacing any existing contents.
81    pub fn set(&mut self, obj: impl Into<T>) {
82        self.obj = Box::new(obj.into());
83    }
84
85    /// Convert into the inner type
86    pub fn into_inner(self) -> T {
87        *self.obj
88    }
89}
90
91impl<const N: usize, T> NullableOffsetMarker<T, N> {
92    /// Create a new marker.
93    pub fn new(obj: Option<T>) -> Self {
94        NullableOffsetMarker {
95            obj: obj.map(|t| Box::new(t)),
96        }
97    }
98
99    /// Set the contents of the marker, replacing any existing contents.
100    ///
101    /// The argument must be some value; to set the offset to null, use the
102    /// [`clear`] method.
103    ///
104    /// [`clear`]: Self::clear
105    pub fn set(&mut self, obj: impl Into<T>) {
106        self.obj = Some(Box::new(obj.into()))
107    }
108
109    /// Clear the contents of the marker.
110    pub fn clear(&mut self) {
111        self.obj = None;
112    }
113
114    /// Convert into the inner type
115    pub fn into_inner(self) -> Option<T> {
116        self.obj.map(|b| *b)
117    }
118
119    pub fn as_ref(&self) -> Option<&T> {
120        match &self.obj {
121            Some(obj) => Some(obj.as_ref()),
122            None => None,
123        }
124    }
125
126    pub fn as_mut(&mut self) -> Option<&mut T> {
127        match &mut self.obj {
128            Some(obj) => Some(&mut *obj),
129            None => None,
130        }
131    }
132}
133
134impl<const N: usize, T: FontWrite> FontWrite for OffsetMarker<T, N> {
135    fn write_into(&self, writer: &mut TableWriter) {
136        writer.write_offset(self.obj.as_ref(), N);
137    }
138
139    fn table_type(&self) -> crate::table_type::TableType {
140        self.obj.table_type()
141    }
142}
143
144impl<const N: usize, T: FontWrite> FontWrite for NullableOffsetMarker<T, N> {
145    fn write_into(&self, writer: &mut TableWriter) {
146        match self.obj.as_ref() {
147            Some(obj) => writer.write_offset(obj.as_ref(), N),
148            None => writer.write_slice([0u8; N].as_slice()),
149        }
150    }
151
152    fn table_type(&self) -> crate::table_type::TableType {
153        match self.obj.as_ref() {
154            Some(obj) => obj.table_type(),
155            None => crate::table_type::TableType::Unknown,
156        }
157    }
158}
159
160impl<T, const N: usize> Default for NullableOffsetMarker<T, N> {
161    fn default() -> Self {
162        Self { obj: None }
163    }
164}
165
166impl<T, const N: usize> From<T> for OffsetMarker<T, N> {
167    fn from(src: T) -> Self {
168        OffsetMarker::new(src)
169    }
170}
171
172impl<T, const N: usize> From<T> for NullableOffsetMarker<T, N> {
173    fn from(src: T) -> Self {
174        NullableOffsetMarker::new(Some(src))
175    }
176}
177
178impl<T, const N: usize> From<Option<T>> for NullableOffsetMarker<T, N> {
179    fn from(src: Option<T>) -> Self {
180        NullableOffsetMarker::new(src)
181    }
182}
183
184// In case I still want to use these?
185
186//impl<T: std::fmt::Debug, const N: usize> std::fmt::Debug for OffsetMarker<T, N> {
187//fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
188//write!(f, "OffsetMarker({}, {:?})", N * 8, self.obj.as_ref(),)
189//}
190//}
191
192//impl<const N: usize, T: std::fmt::Debug> std::fmt::Debug for NullableOffsetMarker<T, N> {
193//fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
194//write!(
195//f,
196//"NullableOffsetMarker({}, {:?})",
197//N * 8,
198//self.obj.as_ref(),
199//)
200//}
201//}