diff --git a/src/ggg/lookup.rs b/src/ggg/lookup.rs index 7d7fc679..66aa3dfd 100644 --- a/src/ggg/lookup.rs +++ b/src/ggg/lookup.rs @@ -70,6 +70,11 @@ impl<'a> LookupSubtables<'a> { self.offsets.len() } + /// Checks if there are any items. + pub fn is_empty(&self) -> bool { + self.offsets.is_empty() + } + /// Parses a subtable at index. /// /// Accepts either @@ -86,6 +91,7 @@ impl<'a> LookupSubtables<'a> { /// Creates an iterator over subtables. /// /// We cannot use `IntoIterator` here, because we have to use user-provided base type. + #[allow(clippy::should_implement_trait)] pub fn into_iter>(self) -> LookupSubtablesIter<'a, T> { LookupSubtablesIter { data: self, diff --git a/src/lib.rs b/src/lib.rs index 408ce2ce..85fbc693 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,6 +38,12 @@ Font parsing starts with a [`Face`]. #![warn(missing_docs)] #![warn(missing_copy_implementations)] #![warn(missing_debug_implementations)] +#![allow(clippy::get_first)] // we use it for readability +#![allow(clippy::identity_op)] // we use it for readability +#![allow(clippy::too_many_arguments)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::field_reassign_with_default)] +#![allow(clippy::upper_case_acronyms)] #[cfg(feature = "std")] #[macro_use] @@ -144,7 +150,7 @@ impl FromData for Magic { /// /// The number is stored as f2.16 #[repr(transparent)] -#[derive(Clone, Copy, PartialEq, Default, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] pub struct NormalizedCoordinate(i16); impl From for NormalizedCoordinate { @@ -305,7 +311,7 @@ impl FromData for Tag { /// /// Used for underline and strikeout. #[repr(C)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct LineMetrics { /// Line position. pub position: i16, @@ -319,7 +325,7 @@ pub struct LineMetrics { /// Doesn't guarantee that `x_min` <= `x_max` and/or `y_min` <= `y_max`. #[repr(C)] #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Rect { pub x_min: i16, pub y_min: i16, @@ -377,7 +383,7 @@ impl BBox { } #[inline] - fn to_rect(&self) -> Option { + fn to_rect(self) -> Option { Some(Rect { x_min: i16::try_num_from(self.x_min)?, y_min: i16::try_num_from(self.y_min)?, @@ -420,7 +426,7 @@ impl OutlineBuilder for DummyOutline { /// A glyph raster image format. #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum RasterImageFormat { PNG, } @@ -428,7 +434,7 @@ pub enum RasterImageFormat { /// A glyph's raster image. /// /// Note, that glyph metrics are in pixels and not in font units. -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct RasterGlyphImage<'a> { /// Horizontal offset. pub x: i16, @@ -507,7 +513,7 @@ impl VarCoords { } /// A list of font face parsing errors. -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum FaceParsingError { /// An attempt to read out of bounds detected. /// diff --git a/src/parser.rs b/src/parser.rs index c4eafe9f..83075020 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -124,7 +124,7 @@ pub struct F2DOT14(pub i16); impl F2DOT14 { /// Converts i16 to f32. #[inline] - pub fn to_f32(&self) -> f32 { + pub fn to_f32(self) -> f32 { f32::from(self.0) / 16384.0 } } @@ -213,6 +213,7 @@ impl TryNumFrom for u16 { } } +#[allow(clippy::manual_range_contains)] impl TryNumFrom for i32 { #[inline] fn try_num_from(v: f32) -> Option { @@ -403,7 +404,7 @@ impl<'a, T: FromData> Iterator for LazyArrayIter16<'a, T> { #[inline] fn count(self) -> usize { - usize::from(self.data.len().checked_sub(self.index).unwrap_or(0)) + usize::from(self.data.len().saturating_sub(self.index)) } } @@ -454,6 +455,11 @@ impl<'a, T: FromData> LazyArray32<'a, T> { (self.data.len() / T::SIZE) as u32 } + /// Checks if the array is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Performs a binary search by specified `key`. #[inline] pub fn binary_search(&self, key: &T) -> Option<(u32, T)> @@ -538,7 +544,7 @@ impl<'a, T: FromData> Iterator for LazyArrayIter32<'a, T> { #[inline] fn count(self) -> usize { - usize::num_from(self.data.len().checked_sub(self.index).unwrap_or(0)) + usize::num_from(self.data.len().saturating_sub(self.index)) } } @@ -641,12 +647,12 @@ impl<'a, T: FromSlice<'a>> Iterator for LazyOffsetArrayIter16<'a, T> { #[inline] fn count(self) -> usize { - usize::from(self.array.len().checked_sub(self.index).unwrap_or(0)) + usize::from(self.array.len().saturating_sub(self.index)) } } /// A streaming binary parser. -#[derive(Clone, Copy, Default, Debug)] +#[derive(Clone, Default, Debug)] pub struct Stream<'a> { data: &'a [u8], offset: usize, diff --git a/src/tables/ankr.rs b/src/tables/ankr.rs index 78437b0d..1d019e65 100644 --- a/src/tables/ankr.rs +++ b/src/tables/ankr.rs @@ -9,7 +9,7 @@ use crate::GlyphId; /// An anchor point. #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Default, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] pub struct Point { pub x: i16, pub y: i16, diff --git a/src/tables/avar.rs b/src/tables/avar.rs index b4ba1fc6..39258110 100644 --- a/src/tables/avar.rs +++ b/src/tables/avar.rs @@ -45,6 +45,11 @@ impl<'a> SegmentMaps<'a> { pub fn len(&self) -> u16 { self.count } + + /// Checks if there are any segments. + pub fn is_empty(&self) -> bool { + self.count == 0 + } } impl core::fmt::Debug for SegmentMaps<'_> { @@ -76,7 +81,7 @@ impl<'a> Iterator for SegmentMapsIter<'a> { fn next(&mut self) -> Option { let count = self.stream.read::()?; - return self.stream.read_array16::(count); + self.stream.read_array16::(count) } } @@ -126,7 +131,7 @@ impl<'a> Table<'a> { fn map_value(map: &LazyArray16, value: i16) -> Option { // This code is based on harfbuzz implementation. - if map.len() == 0 { + if map.is_empty() { return Some(value); } else if map.len() == 1 { let record = map.get(0)?; diff --git a/src/tables/cff/cff1.rs b/src/tables/cff/cff1.rs index 5cf54e0e..9ad3cb43 100644 --- a/src/tables/cff/cff1.rs +++ b/src/tables/cff/cff1.rs @@ -784,7 +784,7 @@ impl FDSelect<'_> { fn font_dict_index(&self, glyph_id: GlyphId) -> Option { match self { FDSelect::Format0(ref array) => array.get(glyph_id.0), - FDSelect::Format3(ref data) => { + FDSelect::Format3(data) => { let mut s = Stream::new(data); let number_of_ranges = s.read::()?; if number_of_ranges == 0 { @@ -842,20 +842,17 @@ fn parse_sid_metadata<'a>( metadata.default_width = private_dict.default_width.unwrap_or(0.0); metadata.nominal_width = private_dict.nominal_width.unwrap_or(0.0); - match ( + if let (Some(private_dict_range), Some(subroutines_offset)) = ( top_dict.private_dict_range, private_dict.local_subroutines_offset, ) { - (Some(private_dict_range), Some(subroutines_offset)) => { - // 'The local subroutines offset is relative to the beginning - // of the Private DICT data.' - if let Some(start) = private_dict_range.start.checked_add(subroutines_offset) { - let data = data.get(start..data.len())?; - let mut s = Stream::new(data); - metadata.local_subrs = parse_index::(&mut s)?; - } + // 'The local subroutines offset is relative to the beginning + // of the Private DICT data.' + if let Some(start) = private_dict_range.start.checked_add(subroutines_offset) { + let data = data.get(start..data.len())?; + let mut s = Stream::new(data); + metadata.local_subrs = parse_index::(&mut s)?; } - _ => {} } Some(FontKind::SID(metadata)) diff --git a/src/tables/cff/index.rs b/src/tables/cff/index.rs index d712b0ba..d320eca0 100644 --- a/src/tables/cff/index.rs +++ b/src/tables/cff/index.rs @@ -31,7 +31,7 @@ fn parse_index_impl<'a>(count: u32, s: &mut Stream<'a>) -> Option> { let offset_size = s.read::()?; let offsets_len = (count + 1).checked_mul(offset_size.to_u32())?; let offsets = VarOffsets { - data: &s.read_bytes(usize::num_from(offsets_len))?, + data: s.read_bytes(usize::num_from(offsets_len))?, offset_size, }; @@ -60,7 +60,7 @@ fn skip_index_impl(count: u32, s: &mut Stream) -> Option<()> { let offset_size = s.read::()?; let offsets_len = (count + 1).checked_mul(offset_size.to_u32())?; let offsets = VarOffsets { - data: &s.read_bytes(usize::num_from(offsets_len))?, + data: s.read_bytes(usize::num_from(offsets_len))?, offset_size, }; @@ -153,7 +153,7 @@ impl<'a> Index<'a> { #[inline] pub fn len(&self) -> u32 { // Last offset points to the byte after the `Object data`. We should skip it. - self.offsets.len().checked_sub(1).unwrap_or(0) + self.offsets.len().saturating_sub(1) } pub fn get(&self, index: u32) -> Option<&'a [u8]> { @@ -184,7 +184,7 @@ impl<'a> Iterator for IndexIter<'a> { } } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum OffsetSize { Size1 = 1, Size2 = 2, diff --git a/src/tables/cff/mod.rs b/src/tables/cff/mod.rs index 8d8828ee..89825bd5 100644 --- a/src/tables/cff/mod.rs +++ b/src/tables/cff/mod.rs @@ -17,7 +17,7 @@ use crate::{BBox, OutlineBuilder}; /// A list of errors that can occur during a CFF glyph outlining. #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CFFError { NoGlyph, ReadOutOfBounds, @@ -75,7 +75,7 @@ impl<'a> Builder<'a> { } /// A type-safe wrapper for string ID. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)] pub struct StringId(u16); impl FromData for StringId { diff --git a/src/tables/cmap/format12.rs b/src/tables/cmap/format12.rs index 8b6eca0b..86134954 100644 --- a/src/tables/cmap/format12.rs +++ b/src/tables/cmap/format12.rs @@ -62,7 +62,7 @@ impl<'a> Subtable12<'a> { .start_glyph_id .checked_add(code_point)? .checked_sub(group.start_char_code)?; - return u16::try_from(id).ok().map(GlyphId); + u16::try_from(id).ok().map(GlyphId) } /// Calls `f` for each codepoint defined in this table. diff --git a/src/tables/cmap/format14.rs b/src/tables/cmap/format14.rs index 2a1938d7..a99ca00f 100644 --- a/src/tables/cmap/format14.rs +++ b/src/tables/cmap/format14.rs @@ -69,7 +69,7 @@ impl FromData for UnicodeRangeRecord { } /// A result of a variation glyph mapping. -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum GlyphVariationResult { /// Glyph was found in the variation encoding table. Found(GlyphId), diff --git a/src/tables/cmap/mod.rs b/src/tables/cmap/mod.rs index 9f203088..4315c58f 100644 --- a/src/tables/cmap/mod.rs +++ b/src/tables/cmap/mod.rs @@ -216,11 +216,16 @@ impl<'a> Subtables<'a> { }) } - /// Returns the number + /// Returns the number of subtables. #[inline] pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if there are any subtables. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl<'a> IntoIterator for Subtables<'a> { diff --git a/src/tables/feat.rs b/src/tables/feat.rs index e57fd14b..a16c98c1 100644 --- a/src/tables/feat.rs +++ b/src/tables/feat.rs @@ -108,6 +108,11 @@ impl<'a> FeatureNames<'a> { pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if there are any feature names. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl<'a> core::fmt::Debug for FeatureNames<'a> { diff --git a/src/tables/glyf.rs b/src/tables/glyf.rs index 871fc2c6..33d95383 100644 --- a/src/tables/glyf.rs +++ b/src/tables/glyf.rs @@ -369,8 +369,8 @@ impl<'a> EndpointsIter<'a> { let prev = self.endpoints.get(self.index - 1).unwrap_or(0); // Malformed font can have endpoints not in increasing order, // so we have to use checked_sub. - self.left = end.checked_sub(prev).unwrap_or(0); - self.left = self.left.checked_sub(1).unwrap_or(0); + self.left = end.saturating_sub(prev); + self.left = self.left.saturating_sub(1); } // Always advance the index, so we can check the current contour number. @@ -508,6 +508,7 @@ impl CompositeGlyphFlags { // It's not defined in the spec, so we are using our own value. pub(crate) const MAX_COMPONENTS: u8 = 32; +#[allow(clippy::comparison_chain)] #[inline] fn outline_impl( loca_table: loca::Table, diff --git a/src/tables/gpos.rs b/src/tables/gpos.rs index 38bd661d..9825140a 100644 --- a/src/tables/gpos.rs +++ b/src/tables/gpos.rs @@ -51,7 +51,7 @@ impl HintingDevice<'_> { let mask = 0xFFFF >> (16 - (1 << f)); let mut delta = i64::from(bits & mask); - if delta >= i64::from(mask + 1 >> 1) { + if delta >= i64::from((mask + 1) >> 1) { delta -= i64::from(mask + 1); } @@ -94,7 +94,7 @@ impl<'a> Device<'a> { 1..=3 => { let start_size = first; let end_size = second; - let count = 1 + (end_size - start_size) >> (4 - format); + let count = (1 + (end_size - start_size)) >> (4 - format); let delta_values = s.read_array16(count)?; Some(Self::Hinting(HintingDevice { start_size, @@ -262,6 +262,11 @@ impl<'a> ValueRecordsArray<'a> { self.len } + /// Checks if the array is empty. + pub fn is_empty(&self) -> bool { + self.len == 0 + } + /// Returns a [`ValueRecord`] at index. pub fn get(&self, index: u16) -> Option> { let start = usize::from(index) * self.value_len; @@ -444,6 +449,11 @@ impl<'a> PairSets<'a> { pub fn len(&self) -> u16 { self.offsets.len() } + + /// Checks if the array is empty. + pub fn is_empty(&self) -> bool { + self.offsets.is_empty() + } } impl core::fmt::Debug for PairSets<'_> { @@ -474,7 +484,7 @@ impl<'a> ClassMatrix<'a> { let count = usize::num_from(u32::from(counts.0) * u32::from(counts.1)); // Max len is 32, so u8 is just enough. let record_len = (flags.0.size() + flags.1.size()) as u8; - let matrix = s.read_bytes(usize::from(count) * usize::from(record_len))?; + let matrix = s.read_bytes(count * usize::from(record_len))?; Some(Self { table_data, matrix, @@ -608,6 +618,11 @@ impl<'a> CursiveAnchorSet<'a> { pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if the set is empty. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl core::fmt::Debug for CursiveAnchorSet<'_> { @@ -743,6 +758,11 @@ impl<'a> LigatureArray<'a> { pub fn len(&self) -> u16 { self.offsets.len() } + + /// Checks if the array is empty. + pub fn is_empty(&self) -> bool { + self.offsets.is_empty() + } } impl core::fmt::Debug for LigatureArray<'_> { @@ -799,6 +819,11 @@ impl<'a> MarkArray<'a> { pub fn len(&self) -> u16 { self.array.len() } + + /// Checks if the array is empty. + pub fn is_empty(&self) -> bool { + self.array.is_empty() + } } impl core::fmt::Debug for MarkArray<'_> { diff --git a/src/tables/gvar.rs b/src/tables/gvar.rs index 1f91af90..1086d9d0 100644 --- a/src/tables/gvar.rs +++ b/src/tables/gvar.rs @@ -3,6 +3,10 @@ // https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-variation-store +// We do have to call clone for readability on some types. +#![allow(clippy::clone_on_copy)] +#![allow(clippy::neg_cmp_op_on_partial_ord)] + use core::cmp; use core::convert::TryFrom; use core::num::NonZeroU16; @@ -1756,7 +1760,8 @@ impl core::fmt::Debug for Table<'_> { } } -fn outline_var_impl<'a>( +#[allow(clippy::comparison_chain)] +fn outline_var_impl( glyf_table: glyf::Table, gvar_table: &Table, glyph_id: GlyphId, @@ -1809,11 +1814,11 @@ fn outline_var_impl<'a>( // Details: // https://docs.microsoft.com/en-us/typography/opentype/spec/gvar#point-numbers-and-processing-for-composite-glyphs - let mut components = glyf::CompositeGlyphIter::new(s.tail()?); + let components = glyf::CompositeGlyphIter::new(s.tail()?); let components_count = components.clone().count() as u16; gvar_table.parse_variation_data(glyph_id, coordinates, components_count, &mut tuples)?; - while let Some(component) = components.next() { + for component in components { let (tx, ty) = tuples.apply_null()?; let mut transform = builder.transform; diff --git a/src/tables/head.rs b/src/tables/head.rs index dc36b51d..3098eafe 100644 --- a/src/tables/head.rs +++ b/src/tables/head.rs @@ -7,7 +7,7 @@ use crate::Rect; /// An index format used by the [Index to Location Table]( /// https://docs.microsoft.com/en-us/typography/opentype/spec/loca). #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum IndexToLocationFormat { Short, Long, @@ -54,7 +54,7 @@ impl Table { s.skip::(); // font direction hint let index_to_location_format = s.read::()?; - if !(units_per_em >= 16 && units_per_em <= 16384) { + if !(16..=16384).contains(&units_per_em) { return None; } diff --git a/src/tables/kern.rs b/src/tables/kern.rs index 41d565f8..22966149 100644 --- a/src/tables/kern.rs +++ b/src/tables/kern.rs @@ -159,6 +159,11 @@ impl<'a> Subtables<'a> { pub fn len(&self) -> u32 { self.count } + + /// Checks if there are any subtables. + pub fn is_empty(&self) -> bool { + self.count == 0 + } } impl core::fmt::Debug for Subtables<'_> { @@ -184,7 +189,7 @@ impl<'a> IntoIterator for Subtables<'a> { /// An iterator over kerning subtables. #[allow(missing_debug_implementations)] -#[derive(Clone, Copy, Default)] +#[derive(Clone, Default)] pub struct SubtablesIter<'a> { /// Indicates an Apple Advanced Typography format. is_aat: bool, diff --git a/src/tables/kerx.rs b/src/tables/kerx.rs index 20a4ff38..9c17ea2d 100644 --- a/src/tables/kerx.rs +++ b/src/tables/kerx.rs @@ -398,7 +398,7 @@ impl<'a> IntoIterator for Subtables<'a> { /// An iterator over extended kerning subtables. #[allow(missing_debug_implementations)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct SubtablesIter<'a> { /// The number of glyphs from the `maxp` table. number_of_glyphs: NonZeroU16, diff --git a/src/tables/loca.rs b/src/tables/loca.rs index 276587c9..41af44f1 100644 --- a/src/tables/loca.rs +++ b/src/tables/loca.rs @@ -57,7 +57,7 @@ impl<'a> Table<'a> { } } - /// Returns offsets length. + /// Returns the number of offsets. #[inline] pub fn len(&self) -> u16 { match self { @@ -66,6 +66,11 @@ impl<'a> Table<'a> { } } + /// Checks if there are any offsets. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns glyph's range in the `glyf` table. #[inline] pub fn glyph_range(&self, glyph_id: GlyphId) -> Option> { diff --git a/src/tables/morx.rs b/src/tables/morx.rs index de80e124..c90489ae 100644 --- a/src/tables/morx.rs +++ b/src/tables/morx.rs @@ -270,7 +270,7 @@ impl core::fmt::Debug for Subtables<'_> { /// An iterator over a metamorphosis chain subtables. #[allow(missing_debug_implementations)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct SubtablesIter<'a> { index: u32, count: u32, @@ -396,7 +396,7 @@ impl core::fmt::Debug for Chains<'_> { /// An iterator over metamorphosis chains. #[allow(missing_debug_implementations)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct ChainsIter<'a> { index: u32, count: u32, diff --git a/src/tables/name.rs b/src/tables/name.rs index 8143e524..4d8a44a1 100644 --- a/src/tables/name.rs +++ b/src/tables/name.rs @@ -42,7 +42,7 @@ pub mod name_id { /// A [platform ID](https://docs.microsoft.com/en-us/typography/opentype/spec/name#platform-ids). #[allow(missing_docs)] -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum PlatformId { Unicode, Macintosh, @@ -75,10 +75,10 @@ fn is_unicode_encoding(platform_id: PlatformId, encoding_id: u16) -> bool { match platform_id { PlatformId::Unicode => true, - PlatformId::Windows => match encoding_id { - WINDOWS_SYMBOL_ENCODING_ID | WINDOWS_UNICODE_BMP_ENCODING_ID => true, - _ => false, - }, + PlatformId::Windows => matches!( + encoding_id, + WINDOWS_SYMBOL_ENCODING_ID | WINDOWS_UNICODE_BMP_ENCODING_ID + ), _ => false, } } @@ -170,17 +170,9 @@ impl<'a> Name<'a> { #[cfg(feature = "std")] impl<'a> core::fmt::Debug for Name<'a> { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - // TODO: https://github.com/rust-lang/rust/issues/50264 - let name = self.to_string(); f.debug_struct("Name") - .field( - "name", - &name - .as_ref() - .map(core::ops::Deref::deref) - .unwrap_or("unsupported encoding"), - ) + .field("name", &name.as_deref().unwrap_or("unsupported encoding")) .field("platform_id", &self.platform_id) .field("encoding_id", &self.encoding_id) .field("language_id", &self.language_id) @@ -229,6 +221,11 @@ impl<'a> Names<'a> { pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if there are any name records. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl core::fmt::Debug for Names<'_> { @@ -272,7 +269,7 @@ impl<'a> Iterator for NamesIter<'a> { #[inline] fn count(self) -> usize { - usize::from(self.names.len().checked_sub(self.index).unwrap_or(0)) + usize::from(self.names.len().saturating_sub(self.index)) } } diff --git a/src/tables/sbix.rs b/src/tables/sbix.rs index 92ea465e..aaf09e7b 100644 --- a/src/tables/sbix.rs +++ b/src/tables/sbix.rs @@ -98,6 +98,11 @@ impl<'a> Strike<'a> { // The last offset simply indicates the glyph data end. We don't need it. self.offsets.len() - 1 } + + /// Checks if there are any glyphs. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl core::fmt::Debug for Strike<'_> { @@ -130,6 +135,11 @@ impl<'a> Strikes<'a> { pub fn len(&self) -> u32 { self.offsets.len() } + + /// Checks if there are any strikes. + pub fn is_empty(&self) -> bool { + self.offsets.is_empty() + } } impl core::fmt::Debug for Strikes<'_> { diff --git a/src/tables/svg.rs b/src/tables/svg.rs index e569bc6e..fc622a77 100644 --- a/src/tables/svg.rs +++ b/src/tables/svg.rs @@ -60,6 +60,11 @@ impl<'a> SvgDocumentsList<'a> { pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if the list is empty. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl core::fmt::Debug for SvgDocumentsList<'_> { @@ -104,7 +109,7 @@ impl<'a> Iterator for SvgDocumentsListIter<'a> { #[inline] fn count(self) -> usize { - usize::from(self.list.len().checked_sub(self.index).unwrap_or(0)) + usize::from(self.list.len().saturating_sub(self.index)) } } diff --git a/src/tables/trak.rs b/src/tables/trak.rs index f0ac2c17..70940940 100644 --- a/src/tables/trak.rs +++ b/src/tables/trak.rs @@ -59,6 +59,11 @@ impl<'a> Tracks<'a> { pub fn len(&self) -> u16 { self.records.len() } + + /// Checks if there are any tracks. + pub fn is_empty(&self) -> bool { + self.records.is_empty() + } } impl<'a> IntoIterator for Tracks<'a> {