use tarrasque::*;
use crate::error::{UNSUPPORTED};
extract! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Format0<'s>(num_glyphs: usize) {
pub glyphs: View<'s, u16, ()> = [(num_glyphs - 1, ())],
}
}
impl<'s> Format0<'s> {
#[inline]
pub fn find_id(&self, index: usize) -> usize {
if index != 0 {
self.glyphs.extract(index - 1).map(usize::from).unwrap_or(0)
} else {
0
}
}
}
extract! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Range1[3] {
pub first: u16 = [],
pub num_glyphs: u8 = [],
}
}
#[inline]
fn extract_range1s<'s>(
stream: &mut Stream<'s>, mut num_glyphs: usize
) -> ExtractResult<'s, View<'s, Range1, ()>> {
let mut count = 0;
let mut index = 0;
while num_glyphs != 0 {
if index + 3 > stream.len() {
return Err(ExtractError::Insufficient(3));
}
num_glyphs -= stream[index + 2] as usize + 1;
count += 1;
index += 3;
}
stream.extract((count, ()))
}
extract! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Format1<'s>(num_glyphs: usize) {
pub ranges: View<'s, Range1, ()> = extract_range1s(stream, num_glyphs - 1)?,
}
}
impl<'s> Format1<'s> {
#[inline]
pub fn find_id(&self, mut index: usize) -> usize {
if index != 0 {
index -= 1;
} else {
return 0;
}
for range in self.ranges.iter() {
if index < range.num_glyphs as usize + 1 {
return range.first as usize + index;
}
index -= range.num_glyphs as usize + 1;
}
0
}
}
extract! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Range2[4] {
pub first: u16 = [],
pub num_glyphs: u16 = [],
}
}
#[inline]
fn extract_range2s<'s>(
stream: &mut Stream<'s>, mut num_glyphs: usize
) -> ExtractResult<'s, View<'s, Range2, ()>> {
let mut count = 0;
let mut index = 0;
while num_glyphs != 0 {
if index + 4 > stream.len() {
return Err(ExtractError::Insufficient(4));
}
num_glyphs -= be_u16(&stream[index + 2..]) as usize + 1;
count += 1;
index += 4;
}
stream.extract((count, ()))
}
extract! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Format2<'s>(num_glyphs: usize) {
pub ranges: View<'s, Range2, ()> = extract_range2s(stream, num_glyphs - 1)?,
}
}
impl<'s> Format2<'s> {
#[inline]
pub fn find_id(&self, mut index: usize) -> usize {
if index != 0 {
index -= 1;
} else {
return 0;
}
for range in self.ranges.iter() {
if index < range.num_glyphs as usize + 1 {
return range.first as usize + index;
}
index -= range.num_glyphs as usize + 1;
}
0
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Charset<'s> {
Format0(Format0<'s>),
Format1(Format1<'s>),
Format2(Format2<'s>),
}
impl<'s> Charset<'s> {
#[inline]
pub fn find_id(&self, index: usize) -> usize {
match self {
Charset::Format0(charset) => charset.find_id(index),
Charset::Format1(charset) => charset.find_id(index),
Charset::Format2(charset) => charset.find_id(index),
}
}
}
impl<'s> Extract<'s, (i32, usize)> for Charset<'s> {
#[inline]
fn extract(
stream: &mut Stream<'s>, (charset, num_glyphs): (i32, usize)
) -> ExtractResult<'s, Self> {
match charset {
0 ..= 2 => Err(ExtractError::Code(UNSUPPORTED)),
_ => match stream.extract::<u8, _>(())? {
0 => Ok(Charset::Format0(stream.extract(num_glyphs)?)),
1 => Ok(Charset::Format1(stream.extract(num_glyphs)?)),
2 => Ok(Charset::Format2(stream.extract(num_glyphs)?)),
_ => Err(ExtractError::Code(UNSUPPORTED)),
},
}
}
}