1 //! raw font bytes
2 
3 use std::ops::{Range, RangeBounds};
4 
5 use types::{BigEndian, FixedSize, Scalar};
6 
7 use crate::array::ComputedArray;
8 use crate::read::{ComputeSize, FontReadWithArgs, FromBytes, ReadError};
9 use crate::table_ref::TableRef;
10 use crate::FontRead;
11 
12 /// A reference to raw binary font data.
13 ///
14 /// This is a wrapper around a byte slice, that provides convenience methods
15 /// for parsing and validating that data.
16 #[derive(Debug, Default, Clone, Copy)]
17 pub struct FontData<'a> {
18     bytes: &'a [u8],
19 }
20 
21 /// A cursor for validating bytes during parsing.
22 ///
23 /// This type improves the ergonomics of validation blah blah
24 ///
25 /// # Note
26 ///
27 /// call `finish` when you're done to ensure you're in bounds
28 #[derive(Debug, Default, Clone, Copy)]
29 pub struct Cursor<'a> {
30     pos: usize,
31     data: FontData<'a>,
32 }
33 
34 impl<'a> FontData<'a> {
35     /// Create a new `FontData` with these bytes.
36     ///
37     /// You generally don't need to do this? It is handled for you when loading
38     /// data from disk, but may be useful in tests.
new(bytes: &'a [u8]) -> Self39     pub const fn new(bytes: &'a [u8]) -> Self {
40         FontData { bytes }
41     }
42 
43     /// The length of the data, in bytes
len(&self) -> usize44     pub fn len(&self) -> usize {
45         self.bytes.len()
46     }
47 
48     /// `true` if the data has a length of zero bytes.
is_empty(&self) -> bool49     pub fn is_empty(&self) -> bool {
50         self.bytes.is_empty()
51     }
52 
53     /// Returns self[pos..]
split_off(&self, pos: usize) -> Option<FontData<'a>>54     pub fn split_off(&self, pos: usize) -> Option<FontData<'a>> {
55         self.bytes.get(pos..).map(|bytes| FontData { bytes })
56     }
57 
58     /// returns self[..pos], and updates self to = self[pos..];
take_up_to(&mut self, pos: usize) -> Option<FontData<'a>>59     pub fn take_up_to(&mut self, pos: usize) -> Option<FontData<'a>> {
60         if pos > self.len() {
61             return None;
62         }
63         let (head, tail) = self.bytes.split_at(pos);
64         self.bytes = tail;
65         Some(FontData { bytes: head })
66     }
67 
slice(&self, range: impl RangeBounds<usize>) -> Option<FontData<'a>>68     pub fn slice(&self, range: impl RangeBounds<usize>) -> Option<FontData<'a>> {
69         let bounds = (range.start_bound().cloned(), range.end_bound().cloned());
70         self.bytes.get(bounds).map(|bytes| FontData { bytes })
71     }
72 
73     /// Read a scalar at the provided location in the data.
read_at<T: Scalar>(&self, offset: usize) -> Result<T, ReadError>74     pub fn read_at<T: Scalar>(&self, offset: usize) -> Result<T, ReadError> {
75         self.bytes
76             .get(offset..offset + T::RAW_BYTE_LEN)
77             .and_then(T::read)
78             .ok_or(ReadError::OutOfBounds)
79     }
80 
81     /// Read a big-endian value at the provided location in the data.
read_be_at<T: Scalar>(&self, offset: usize) -> Result<BigEndian<T>, ReadError>82     pub fn read_be_at<T: Scalar>(&self, offset: usize) -> Result<BigEndian<T>, ReadError> {
83         self.bytes
84             .get(offset..offset + T::RAW_BYTE_LEN)
85             .and_then(BigEndian::from_slice)
86             .ok_or(ReadError::OutOfBounds)
87     }
88 
read_with_args<T>(&self, range: Range<usize>, args: &T::Args) -> Result<T, ReadError> where T: FontReadWithArgs<'a>,89     pub fn read_with_args<T>(&self, range: Range<usize>, args: &T::Args) -> Result<T, ReadError>
90     where
91         T: FontReadWithArgs<'a>,
92     {
93         self.slice(range)
94             .ok_or(ReadError::OutOfBounds)
95             .and_then(|data| T::read_with_args(data, args))
96     }
97 
check_in_bounds(&self, offset: usize) -> Result<(), ReadError>98     fn check_in_bounds(&self, offset: usize) -> Result<(), ReadError> {
99         self.bytes
100             .get(..offset)
101             .ok_or(ReadError::OutOfBounds)
102             .map(|_| ())
103     }
104 
105     /// Interpret the bytes at the provided offset as a reference to `T`.
106     ///
107     /// Returns an error if the slice `offset..` is shorter than `T::RAW_BYTE_LEN`.
108     ///
109     /// This is a wrapper around [`read_ref_unchecked`][], which panics if
110     /// the type does not uphold the required invariants.
111     ///
112     /// # Panics
113     ///
114     /// This function will panic if `T` is zero-sized, has an alignment
115     /// other than one, or has any internal padding.
116     ///
117     /// [`read_ref_unchecked`]: [Self::read_ref_unchecked]
read_ref_at<T: FromBytes>(&self, offset: usize) -> Result<&'a T, ReadError>118     pub fn read_ref_at<T: FromBytes>(&self, offset: usize) -> Result<&'a T, ReadError> {
119         assert_ne!(std::mem::size_of::<T>(), 0);
120         // assert we have no padding.
121         // `T::RAW_BYTE_LEN` is computed by recursively taking the raw length of
122         // any fields of `T`; if `size_of::<T>() == T::RAW_BYTE_LEN`` we know that
123         // `T` contains no padding.
124         assert_eq!(std::mem::size_of::<T>(), T::RAW_BYTE_LEN);
125         assert_eq!(std::mem::align_of::<T>(), 1);
126         self.bytes
127             .get(offset..offset + T::RAW_BYTE_LEN)
128             .ok_or(ReadError::OutOfBounds)?;
129 
130         // SAFETY: if we have reached this point without hitting an assert or
131         // returning an error, our invariants are met.
132         unsafe { Ok(self.read_ref_unchecked(offset)) }
133     }
134 
135     /// Interpret the bytes at `offset` as a reference to some type `T`.
136     ///
137     /// # Safety
138     ///
139     /// `T` must be a struct or scalar that has alignment of 1, a non-zero size,
140     /// and no internal padding, and offset must point to a slice of bytes that
141     /// has length >= `size_of::<T>()`.
read_ref_unchecked<T: FromBytes>(&self, offset: usize) -> &'a T142     unsafe fn read_ref_unchecked<T: FromBytes>(&self, offset: usize) -> &'a T {
143         let bytes = self.bytes.get_unchecked(offset..offset + T::RAW_BYTE_LEN);
144         &*(bytes.as_ptr() as *const T)
145     }
146 
147     /// Interpret the bytes at the provided offset as a slice of `T`.
148     ///
149     /// Returns an error if `range` is out of bounds for the underlying data,
150     /// or if the length of the range is not a multiple of `T::RAW_BYTE_LEN`.
151     ///
152     /// This is a wrapper around [`read_array_unchecked`][], which panics if
153     /// the type does not uphold the required invariants.
154     ///
155     /// # Panics
156     ///
157     /// This function will panic if `T` is zero-sized, has an alignment
158     /// other than one, or has any internal padding.
159     ///
160     /// [`read_array_unchecked`]: [Self::read_array_unchecked]
read_array<T: FromBytes>(&self, range: Range<usize>) -> Result<&'a [T], ReadError>161     pub fn read_array<T: FromBytes>(&self, range: Range<usize>) -> Result<&'a [T], ReadError> {
162         assert_ne!(std::mem::size_of::<T>(), 0);
163         // assert we have no padding.
164         // `T::RAW_BYTE_LEN` is computed by recursively taking the raw length of
165         // any fields of `T`; if `size_of::<T>() == T::RAW_BYTE_LEN`` we know that
166         // `T` contains no padding.
167         assert_eq!(std::mem::size_of::<T>(), T::RAW_BYTE_LEN);
168         assert_eq!(std::mem::align_of::<T>(), 1);
169         let bytes = self
170             .bytes
171             .get(range.clone())
172             .ok_or(ReadError::OutOfBounds)?;
173         if bytes.len() % std::mem::size_of::<T>() != 0 {
174             return Err(ReadError::InvalidArrayLen);
175         };
176         // SAFETY: if we have reached this point without hitting an assert or
177         // returning an error, our invariants are met.
178         unsafe { Ok(self.read_array_unchecked(range)) }
179     }
180 
181     /// Interpret the bytes at `offset` as a reference to some type `T`.
182     ///
183     /// # Safety
184     ///
185     /// `T` must be a struct or scalar that has alignment of 1, a non-zero size,
186     /// and no internal padding, and `range` must have a length that is non-zero
187     /// and is a multiple of `size_of::<T>()`.
read_array_unchecked<T: FromBytes>(&self, range: Range<usize>) -> &'a [T]188     unsafe fn read_array_unchecked<T: FromBytes>(&self, range: Range<usize>) -> &'a [T] {
189         let bytes = self.bytes.get_unchecked(range);
190         let elems = bytes.len() / std::mem::size_of::<T>();
191         std::slice::from_raw_parts(bytes.as_ptr() as *const _, elems)
192     }
193 
cursor(&self) -> Cursor<'a>194     pub(crate) fn cursor(&self) -> Cursor<'a> {
195         Cursor {
196             pos: 0,
197             data: *self,
198         }
199     }
200 
201     /// Return the data as a byte slice
as_bytes(&self) -> &'a [u8]202     pub fn as_bytes(&self) -> &'a [u8] {
203         self.bytes
204     }
205 }
206 
207 impl<'a> Cursor<'a> {
advance<T: Scalar>(&mut self)208     pub(crate) fn advance<T: Scalar>(&mut self) {
209         self.pos += T::RAW_BYTE_LEN
210     }
211 
advance_by(&mut self, n_bytes: usize)212     pub(crate) fn advance_by(&mut self, n_bytes: usize) {
213         self.pos += n_bytes;
214     }
215 
216     /// Read a scalar and advance the cursor.
read<T: Scalar>(&mut self) -> Result<T, ReadError>217     pub(crate) fn read<T: Scalar>(&mut self) -> Result<T, ReadError> {
218         let temp = self.data.read_at(self.pos);
219         self.pos += T::RAW_BYTE_LEN;
220         temp
221     }
222 
223     /// Read a big-endian value and advance the cursor.
read_be<T: Scalar>(&mut self) -> Result<BigEndian<T>, ReadError>224     pub(crate) fn read_be<T: Scalar>(&mut self) -> Result<BigEndian<T>, ReadError> {
225         let temp = self.data.read_be_at(self.pos);
226         self.pos += T::RAW_BYTE_LEN;
227         temp
228     }
229 
read_with_args<T>(&mut self, args: &T::Args) -> Result<T, ReadError> where T: FontReadWithArgs<'a> + ComputeSize,230     pub(crate) fn read_with_args<T>(&mut self, args: &T::Args) -> Result<T, ReadError>
231     where
232         T: FontReadWithArgs<'a> + ComputeSize,
233     {
234         let len = T::compute_size(args);
235         let temp = self.data.read_with_args(self.pos..self.pos + len, args);
236         self.pos += len;
237         temp
238     }
239 
240     // only used in records that contain arrays :/
read_computed_array<T>( &mut self, len: usize, args: &T::Args, ) -> Result<ComputedArray<'a, T>, ReadError> where T: FontReadWithArgs<'a> + ComputeSize,241     pub(crate) fn read_computed_array<T>(
242         &mut self,
243         len: usize,
244         args: &T::Args,
245     ) -> Result<ComputedArray<'a, T>, ReadError>
246     where
247         T: FontReadWithArgs<'a> + ComputeSize,
248     {
249         let len = len * T::compute_size(args);
250         let temp = self.data.read_with_args(self.pos..self.pos + len, args);
251         self.pos += len;
252         temp
253     }
254 
read_array<T: FromBytes>(&mut self, n_elem: usize) -> Result<&'a [T], ReadError>255     pub(crate) fn read_array<T: FromBytes>(&mut self, n_elem: usize) -> Result<&'a [T], ReadError> {
256         let len = n_elem * T::RAW_BYTE_LEN;
257         let temp = self.data.read_array(self.pos..self.pos + len);
258         self.pos += len;
259         temp
260     }
261 
262     /// read a value, validating it with the provided function if successful.
263     //pub(crate) fn read_validate<T, F>(&mut self, f: F) -> Result<T, ReadError>
264     //where
265     //T: ReadScalar,
266     //F: FnOnce(&T) -> bool,
267     //{
268     //let temp = self.read()?;
269     //if f(&temp) {
270     //Ok(temp)
271     //} else {
272     //Err(ReadError::ValidationError)
273     //}
274     //}
275 
276     //pub(crate) fn check_array<T: Scalar>(&mut self, len_bytes: usize) -> Result<(), ReadError> {
277     //assert_ne!(std::mem::size_of::<BigEndian<T>>(), 0);
278     //assert_eq!(std::mem::align_of::<BigEndian<T>>(), 1);
279     //if len_bytes % T::SIZE != 0 {
280     //return Err(ReadError::InvalidArrayLen);
281     //}
282     //self.data.check_in_bounds(self.pos + len_bytes)
283     //todo!()
284     //}
285 
286     /// return the current position, or an error if we are out of bounds
position(&self) -> Result<usize, ReadError>287     pub(crate) fn position(&self) -> Result<usize, ReadError> {
288         self.data.check_in_bounds(self.pos).map(|_| self.pos)
289     }
290 
291     // used when handling fields with an implicit length, which must be at the
292     // end of a table.
remaining_bytes(&self) -> usize293     pub(crate) fn remaining_bytes(&self) -> usize {
294         self.data.len().saturating_sub(self.pos)
295     }
296 
finish<T>(self, shape: T) -> Result<TableRef<'a, T>, ReadError>297     pub(crate) fn finish<T>(self, shape: T) -> Result<TableRef<'a, T>, ReadError> {
298         let data = self.data;
299         data.check_in_bounds(self.pos)?;
300         Ok(TableRef { data, shape })
301     }
302 }
303 
304 // useful so we can have offsets that are just to data
305 impl<'a> FontRead<'a> for FontData<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>306     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
307         Ok(data)
308     }
309 }
310 
311 impl AsRef<[u8]> for FontData<'_> {
as_ref(&self) -> &[u8]312     fn as_ref(&self) -> &[u8] {
313         self.bytes
314     }
315 }
316 
317 impl<'a> From<&'a [u8]> for FontData<'a> {
from(src: &'a [u8]) -> FontData<'a>318     fn from(src: &'a [u8]) -> FontData<'a> {
319         FontData::new(src)
320     }
321 }
322 
323 //kind of ugly, but makes FontData work with FontBuilder. If FontBuilder stops using
324 //Cow in its API, we can probably get rid of this?
325 #[cfg(feature = "std")]
326 impl<'a> From<FontData<'a>> for std::borrow::Cow<'a, [u8]> {
from(src: FontData<'a>) -> Self327     fn from(src: FontData<'a>) -> Self {
328         src.bytes.into()
329     }
330 }
331