use crate::offset::ResolveNullableOffset;
use font_types::{BigEndian, Nullable, Offset16, Scalar};
use crate::{FontData, FontReadWithArgs, Offset, ReadArgs, ReadError, ResolveOffset};
#[derive(Clone)]
pub struct ArrayOfOffsets<'a, T: ReadArgs, O: Scalar = Offset16> {
offsets: &'a [BigEndian<O>],
data: FontData<'a>,
args: T::Args,
}
#[derive(Clone)]
pub struct ArrayOfNullableOffsets<'a, T: ReadArgs, O: Scalar = Offset16> {
offsets: &'a [BigEndian<Nullable<O>>],
data: FontData<'a>,
args: T::Args,
}
impl<'a, T, O> ArrayOfOffsets<'a, T, O>
where
O: Scalar,
T: ReadArgs,
{
pub(crate) fn new(offsets: &'a [BigEndian<O>], data: FontData<'a>, args: T::Args) -> Self {
Self {
offsets,
data,
args,
}
}
}
impl<'a, T, O> ArrayOfOffsets<'a, T, O>
where
O: Scalar + Offset,
T: ReadArgs + FontReadWithArgs<'a>,
T::Args: Copy + 'static,
{
pub fn len(&self) -> usize {
self.offsets.len()
}
pub fn is_empty(&self) -> bool {
self.offsets.is_empty()
}
pub fn get(&self, idx: usize) -> Result<T, ReadError> {
self.offsets
.get(idx)
.ok_or(ReadError::InvalidCollectionIndex(idx as _))
.and_then(|o| o.get().resolve_with_args(self.data, &self.args))
}
pub fn iter(&self) -> impl Iterator<Item = Result<T, ReadError>> + 'a {
let mut iter = self.offsets.iter();
let args = self.args;
let data = self.data;
std::iter::from_fn(move || {
iter.next()
.map(|off| off.get().resolve_with_args(data, &args))
})
}
}
impl<'a, T, O> ArrayOfNullableOffsets<'a, T, O>
where
O: Scalar + Offset,
T: ReadArgs,
{
pub(crate) fn new(
offsets: &'a [BigEndian<Nullable<O>>],
data: FontData<'a>,
args: T::Args,
) -> Self {
Self {
offsets,
data,
args,
}
}
}
impl<'a, T, O> ArrayOfNullableOffsets<'a, T, O>
where
O: Scalar + Offset,
T: ReadArgs + FontReadWithArgs<'a>,
T::Args: Copy + 'static,
{
pub fn len(&self) -> usize {
self.offsets.len()
}
pub fn is_empty(&self) -> bool {
self.offsets.is_empty()
}
pub fn get(&self, idx: usize) -> Option<Result<T, ReadError>> {
let Some(offset) = self.offsets.get(idx) else {
return Some(Err(ReadError::InvalidCollectionIndex(idx as _)));
};
offset.get().resolve_with_args(self.data, &self.args)
}
pub fn iter(&self) -> impl Iterator<Item = Option<Result<T, ReadError>>> + 'a {
let mut iter = self.offsets.iter();
let args = self.args;
let data = self.data;
std::iter::from_fn(move || {
iter.next()
.map(|off| off.get().resolve_with_args(data, &args))
})
}
}