Skip to main content

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