use super::{ClassDefinition, Coverage, LookupIndex};
use crate::parser::{FromData, FromSlice, LazyArray16, LazyOffsetArray16, Stream};
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum ContextLookup<'a> {
Format1 {
coverage: Coverage<'a>,
sets: SequenceRuleSets<'a>,
},
Format2 {
coverage: Coverage<'a>,
classes: ClassDefinition<'a>,
sets: SequenceRuleSets<'a>,
},
Format3 {
coverage: Coverage<'a>,
coverages: LazyOffsetArray16<'a, Coverage<'a>>,
lookups: LazyArray16<'a, SequenceLookupRecord>,
},
}
impl<'a> ContextLookup<'a> {
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
match s.read::<u16>()? {
1 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format1 {
coverage,
sets: SequenceRuleSets::new(data, offsets),
})
}
2 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format2 {
coverage,
classes,
sets: SequenceRuleSets::new(data, offsets),
})
}
3 => {
let input_count = s.read::<u16>()?;
let lookup_count = s.read::<u16>()?;
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let coverages = s.read_array16(input_count.checked_sub(1)?)?;
let lookups = s.read_array16(lookup_count)?;
Some(Self::Format3 {
coverage,
coverages: LazyOffsetArray16::new(data, coverages),
lookups,
})
}
_ => None,
}
}
#[inline]
pub fn coverage(&self) -> Coverage<'a> {
match self {
Self::Format1 { coverage, .. } => *coverage,
Self::Format2 { coverage, .. } => *coverage,
Self::Format3 { coverage, .. } => *coverage,
}
}
}
pub type SequenceRuleSets<'a> = LazyOffsetArray16<'a, SequenceRuleSet<'a>>;
impl<'a> FromSlice<'a> for SequenceRuleSet<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
Self::parse(data)
}
}
impl<'a> FromSlice<'a> for SequenceRule<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let input_count = s.read::<u16>()?;
let lookup_count = s.read::<u16>()?;
let input = s.read_array16(input_count.checked_sub(1)?)?;
let lookups = s.read_array16(lookup_count)?;
Some(Self { input, lookups })
}
}
pub type SequenceRuleSet<'a> = LazyOffsetArray16<'a, SequenceRule<'a>>;
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct SequenceRule<'a> {
pub input: LazyArray16<'a, u16>,
pub lookups: LazyArray16<'a, SequenceLookupRecord>,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct SequenceLookupRecord {
pub sequence_index: u16,
pub lookup_list_index: LookupIndex,
}
impl FromData for SequenceLookupRecord {
const SIZE: usize = 4;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
sequence_index: s.read::<u16>()?,
lookup_list_index: s.read::<LookupIndex>()?,
})
}
}