Skip to content

Commit

Permalink
Reduce allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
laurmaedje committed Jun 7, 2022
1 parent 8e16d33 commit e101776
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 69 deletions.
36 changes: 18 additions & 18 deletions src/cff/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use crate::{Error, Reader, Result, Structure, Writer};

/// A DICT data structure.
#[derive(Clone)]
pub struct Dict(Vec<Pair>);
pub struct Dict<'a>(Vec<Pair<'a>>);

impl Dict {
impl<'a> Dict<'a> {
pub fn new() -> Self {
Self(vec![])
}

pub fn get(&self, op: Op) -> Option<&[Operand]> {
pub fn get(&self, op: Op) -> Option<&[Operand<'a>]> {
self.0
.iter()
.find(|pair| pair.op == op)
Expand Down Expand Up @@ -43,7 +43,7 @@ impl Dict {
}
}

pub fn set(&mut self, op: Op, operands: Vec<Operand>) {
pub fn set(&mut self, op: Op, operands: Vec<Operand<'a>>) {
if let Some(pair) = self.0.iter_mut().find(|pair| pair.op == op) {
pair.operands = operands;
} else {
Expand All @@ -63,8 +63,8 @@ impl Dict {
}
}

impl Structure for Dict {
fn read(r: &mut Reader) -> Result<Self> {
impl<'a> Structure<'a> for Dict<'a> {
fn read(r: &mut Reader<'a>) -> Result<Self> {
let mut pairs = vec![];
while !r.eof() {
pairs.push(r.read::<Pair>()?);
Expand All @@ -79,21 +79,21 @@ impl Structure for Dict {
}
}

impl Debug for Dict {
impl Debug for Dict<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_list().entries(self.0.iter()).finish()
}
}

/// An operand-operator pair in a DICT.
#[derive(Clone)]
struct Pair {
operands: Vec<Operand>,
struct Pair<'a> {
operands: Vec<Operand<'a>>,
op: Op,
}

impl Structure for Pair {
fn read(r: &mut Reader) -> Result<Self> {
impl<'a> Structure<'a> for Pair<'a> {
fn read(r: &mut Reader<'a>) -> Result<Self> {
let mut operands = vec![];
loop {
match r.data().first().ok_or(Error::MissingData)? {
Expand All @@ -113,7 +113,7 @@ impl Structure for Pair {
}
}

impl Debug for Pair {
impl Debug for Pair<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}: {:?}", self.op, self.operands)
}
Expand All @@ -123,7 +123,7 @@ impl Debug for Pair {
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Op(u8, u8);

impl Structure for Op {
impl Structure<'_> for Op {
fn read(r: &mut Reader) -> Result<Self> {
let b0 = r.read::<u8>()?;
match b0 {
Expand All @@ -143,14 +143,14 @@ impl Structure for Op {

/// An operand in a DICT.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Operand {
pub enum Operand<'a> {
Int(i32),
Offset(usize),
Real(Vec<u8>),
Real(&'a [u8]),
}

impl Structure for Operand {
fn read(r: &mut Reader) -> Result<Self> {
impl<'a> Structure<'a> for Operand<'a> {
fn read(r: &mut Reader<'a>) -> Result<Self> {
let b0 = i32::from(r.read::<u8>()?);
Ok(match b0 {
28 => Self::Int(i32::from(r.read::<i16>()?)),
Expand All @@ -163,7 +163,7 @@ impl Structure for Operand {
break;
}
}
Self::Real(r.take(len)?.to_vec())
Self::Real(r.take(len)?)
}
32 ..= 246 => Self::Int(b0 - 139),
247 ..= 250 => {
Expand Down
8 changes: 4 additions & 4 deletions src/cff/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ impl<T> Index<T> {
}
}

impl<T> Structure for Index<T>
impl<'a, T> Structure<'a> for Index<T>
where
T: Structure,
T: Structure<'a>,
{
fn read(r: &mut Reader) -> Result<Self> {
fn read(r: &mut Reader<'a>) -> Result<Self> {
let data = r.data();
let count = r.read::<u16>()? as usize;
if count == 0 {
Expand Down Expand Up @@ -116,7 +116,7 @@ impl Offsize {
}
}

impl Structure for Offsize {
impl Structure<'_> for Offsize {
fn read(r: &mut Reader) -> Result<Self> {
match r.read::<u8>()? {
1 => Ok(Self::One),
Expand Down
47 changes: 22 additions & 25 deletions src/cff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ use self::index::*;
use super::*;

/// A CFF table.
struct Table {
name: Index<Opaque>,
top_dict: Dict,
strings: Index<Opaque>,
global_subrs: Index<Opaque>,
char_strings: Index<Opaque>,
charset: Option<Opaque>,
private_dict: Option<Dict>,
local_subrs: Option<Index<Opaque>>,
struct Table<'a> {
name: Index<Opaque<'a>>,
top_dict: Dict<'a>,
strings: Index<Opaque<'a>>,
global_subrs: Index<Opaque<'a>>,
char_strings: Index<Opaque<'a>>,
charset: Option<Opaque<'a>>,
private_dict: Option<Dict<'a>>,
local_subrs: Option<Index<Opaque<'a>>>,
}

/// Recorded offsets that will be written into DICTs.
Expand Down Expand Up @@ -209,7 +209,7 @@ fn set_offets(table: &mut Table, offsets: &Offsets) {
/// Subset a Top DICT.
///
/// Keeps only relevant non-offset entries. Offset entries are inserted later.
fn subset_top(top_dict: &Dict) -> Dict {
fn subset_top<'a>(top_dict: &Dict<'a>) -> Dict<'a> {
let mut sub = Dict::new();
sub.copy(&top_dict, top::ROS);
sub.copy(&top_dict, top::CID_FONT_VERSION);
Expand Down Expand Up @@ -241,7 +241,7 @@ fn subset_top(top_dict: &Dict) -> Dict {
/// Subset a Private DICT.
///
/// Keeps only relevant non-offset entries. Offset entries are inserted later.
fn subset_private(private_dict: &Dict) -> Dict {
fn subset_private<'a>(private_dict: &Dict<'a>) -> Dict<'a> {
let mut sub = Dict::new();
sub.copy(&private_dict, private::BLUE_VALUES);
sub.copy(&private_dict, private::OTHER_BLUES);
Expand All @@ -264,7 +264,7 @@ fn subset_private(private_dict: &Dict) -> Dict {
}

/// Extract the charset bytes.
fn read_charset(data: &[u8], num_glyphs: u16) -> Result<Opaque> {
fn read_charset(data: &[u8], num_glyphs: u16) -> Result<Opaque<'_>> {
let mut r = Reader::new(data);
let mut len = 1;

Expand Down Expand Up @@ -294,37 +294,34 @@ fn read_charset(data: &[u8], num_glyphs: u16) -> Result<Opaque> {
_ => return Err(Error::InvalidData),
}

Ok(Opaque(
data.get(.. len).ok_or(Error::InvalidOffset)?.to_vec(),
))
Ok(Opaque(data.get(.. len).ok_or(Error::InvalidOffset)?))
}

/// Subset the glyph descriptions.
fn subset_char_strings(
fn subset_char_strings<'a>(
ctx: &Context,
mut strings: Index<Opaque>,
) -> Result<Index<Opaque>> {
mut strings: Index<Opaque<'a>>,
) -> Result<Index<Opaque<'a>>> {
// The set of all glyphs we will include in the subset.
let subset: HashSet<u16> = ctx.profile.glyphs.iter().copied().collect();

for glyph in 0 .. ctx.num_glyphs {
if !subset.contains(&glyph) {
// The byte sequence [14] is the minimal valid charstring consisting
// of just a single `endchar` operator.
*strings.get_mut(glyph as usize).ok_or(Error::InvalidOffset)? =
Opaque(vec![14]);
*strings.get_mut(glyph as usize).ok_or(Error::InvalidOffset)? = Opaque(&[14]);
}
}

Ok(strings)
}

/// An opaque binary data structure.
struct Opaque(Vec<u8>);
struct Opaque<'a>(&'a [u8]);

impl Structure for Opaque {
fn read(r: &mut Reader) -> Result<Self> {
let data = r.data().to_vec();
impl<'a> Structure<'a> for Opaque<'a> {
fn read(r: &mut Reader<'a>) -> Result<Self> {
let data = r.data();
r.skip(data.len())?;
Ok(Self(data))
}
Expand All @@ -334,7 +331,7 @@ impl Structure for Opaque {
}
}

impl Debug for Opaque {
impl Debug for Opaque<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad("Opaque { .. }")
}
Expand Down
10 changes: 5 additions & 5 deletions src/glyf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ pub(crate) fn subset(ctx: &mut Context) -> Result<()> {
}
}

fn subset_impl<T>(ctx: &mut Context) -> Result<()>
fn subset_impl<'a, T>(ctx: &'a mut Context) -> Result<()>
where
T: LocaOffset,
T: LocaOffset<'a>,
{
let loca = ctx.expect_table(Tag::LOCA)?;
let glyf = ctx.expect_table(Tag::GLYF)?;
Expand Down Expand Up @@ -121,12 +121,12 @@ fn component_glyphs(mut r: Reader) -> impl Iterator<Item = u16> + '_ {
}

/// A loca offset, either 16-bit or 32-bit.
trait LocaOffset: Structure {
trait LocaOffset<'a>: Structure<'a> {
fn loca_to_usize(self) -> usize;
fn usize_to_loca(offset: usize) -> Self;
}

impl LocaOffset for u16 {
impl LocaOffset<'_> for u16 {
fn loca_to_usize(self) -> usize {
2 * usize::from(self)
}
Expand All @@ -138,7 +138,7 @@ impl LocaOffset for u16 {
}
}

impl LocaOffset for u32 {
impl LocaOffset<'_> for u32 {
fn loca_to_usize(self) -> usize {
self as usize
}
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl Tag {
const SVG: Self = Self(*b"SVG ");
}

impl Structure for Tag {
impl Structure<'_> for Tag {
fn read(r: &mut Reader) -> Result<Self> {
r.read::<[u8; 4]>().map(Self)
}
Expand Down Expand Up @@ -346,7 +346,7 @@ enum FontKind {
Collection,
}

impl Structure for FontKind {
impl Structure<'_> for FontKind {
fn read(r: &mut Reader) -> Result<Self> {
match r.read::<u32>()? {
0x00010000 | 0x74727565 => Ok(FontKind::TrueType),
Expand All @@ -368,7 +368,7 @@ impl Structure for FontKind {
/// A signed 16-bit fixed-point number.
struct F2Dot14(u16);

impl Structure for F2Dot14 {
impl Structure<'_> for F2Dot14 {
fn read(r: &mut Reader) -> Result<Self> {
r.read::<u16>().map(Self)
}
Expand All @@ -387,7 +387,7 @@ struct TableRecord {
length: u32,
}

impl Structure for TableRecord {
impl Structure<'_> for TableRecord {
fn read(r: &mut Reader) -> Result<Self> {
Ok(TableRecord {
tag: r.read::<Tag>()?,
Expand Down
Loading

0 comments on commit e101776

Please sign in to comment.