From 041720c3d991a7f9154e71503093180877c9e427 Mon Sep 17 00:00:00 2001 From: Henrik Lievonen Date: Sun, 19 Nov 2023 17:07:20 +0200 Subject: [PATCH] chore!: Move map and set to modules --- src/font_face.rs | 4 +++- src/lib.rs | 12 +++++------- src/map.rs | 34 +++++++++++++++++++--------------- src/set.rs | 47 +++++++++++++++++++++++++++-------------------- src/subset.rs | 6 +++++- 5 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/font_face.rs b/src/font_face.rs index aa8f12a..fd47617 100644 --- a/src/font_face.rs +++ b/src/font_face.rs @@ -1,6 +1,8 @@ use std::{ffi::c_char, marker::PhantomData, ops::Deref, ptr::null_mut}; -use crate::{sys, AllocationError, Blob, CharSet, FontFaceExtractionError, Language, Map}; +use crate::{ + map::Map, set::CharSet, sys, AllocationError, Blob, FontFaceExtractionError, Language, +}; /// A font face is an object that represents a single face from within a font family. /// diff --git a/src/lib.rs b/src/lib.rs index d11e4f1..c18ac51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,13 +17,13 @@ //! In other words, subsetting allows you to take a large font and construct a new, smaller font which has only those //! characters that you need. Be sure to check the license of the font though, as not all fonts can be legally //! subsetted. -//! +//! //! # Why? //! Many modern fonts can contain hundreds or even thousands of glyphs, of which only a couple dozen or maybe hundred is //! needed in any single document. This also means that modern fonts can be very bulky compared to what is actually //! needed. The solution to this is font subsetting: We can construct a font that includes only those glyphs and //! features that are needed for the document. -//! +//! //! # Usage //! The simplest way to construct a subset of a font is to use [`subset()`] function. In the following example, we keep //! only glyphs that are needed show any combination of characters 'a', 'b' and 'c', e.g. "abc" and "cabba" can be @@ -59,7 +59,7 @@ //! # Ok(()) //! # } //! ``` -//! +//! //! # Using bundled version of HarfBuzz //! By default, this crate uses the system HarfBuzz installation. If it is not available, or it is too old, this crate //! can also used a bundled copy of HarfBuzz by using feature `bundled`: @@ -73,8 +73,8 @@ mod blob; mod common; mod error; mod font_face; -mod map; -mod set; +pub mod map; +pub mod set; mod subset; pub mod sys; @@ -83,8 +83,6 @@ pub use blob::*; pub use common::*; pub use error::*; pub use font_face::*; -pub use map::*; -pub use set::*; pub use subset::*; /// A convenient method to create a subset of a font over given characters. diff --git a/src/map.rs b/src/map.rs index 852c561..1170e1b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,3 +1,9 @@ +//! Map represents an integer-to-integer mapping. +//! +//! While map in this module can be used as a general-purpose map in Rust code, it is recommended that you instead use +//! [`std::collections::BTreeMap`] or [`std::collections::HashMap`] as those are implemented directly in Rust and do not +//! rely on FFI to work. + use std::{ fmt, hash::Hash, @@ -5,7 +11,7 @@ use std::{ marker::PhantomData, }; -use crate::{sys, AllocationError, Set}; +use crate::{set::Set, sys, AllocationError}; /// Map objects are integer-to-integer hash-maps. /// @@ -124,10 +130,9 @@ where { /// Gets an iterator over key-value pairs stored in the map. #[doc(alias = "hb_map_next")] - pub fn iter(&self) -> MapIter<'_, 'a, K, V> { - MapIter( - MapIterImpl::new(self) - .filter_map(|(k, v)| Some((k.try_into().ok()?, v.try_into().ok()?))), + pub fn iter(&self) -> Iter<'_, 'a, K, V> { + Iter( + IterImpl::new(self).filter_map(|(k, v)| Some((k.try_into().ok()?, v.try_into().ok()?))), ) } } @@ -217,7 +222,7 @@ where V: TryFrom, { type Item = (K, V); - type IntoIter = MapIter<'m, 'a, K, V>; + type IntoIter = Iter<'m, 'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter() @@ -226,12 +231,11 @@ where /// Iterator over [`Map`] key-value pairs. /// -/// Use [`Map::iter`] to construct [`MapIter`]. -pub struct MapIter<'m, 'a, K, V>(MapIterFilter<'m, 'a, K, V>); -type MapIterFilter<'m, 'a, K, V> = - FilterMap, fn((u32, u32)) -> Option<(K, V)>>; +/// Use [`Map::iter`] to construct [`Iter`]. +pub struct Iter<'m, 'a, K, V>(IterFilter<'m, 'a, K, V>); +type IterFilter<'m, 'a, K, V> = FilterMap, fn((u32, u32)) -> Option<(K, V)>>; -impl<'m, 'a, K, V> Iterator for MapIter<'m, 'a, K, V> +impl<'m, 'a, K, V> Iterator for Iter<'m, 'a, K, V> where K: TryFrom, V: TryFrom, @@ -243,7 +247,7 @@ where } } -impl<'m, 'a, K, V> FusedIterator for MapIter<'m, 'a, K, V> +impl<'m, 'a, K, V> FusedIterator for Iter<'m, 'a, K, V> where K: TryFrom, V: TryFrom, @@ -251,15 +255,15 @@ where } /// Iterator over raw elements over map, disregarding whether they can be represented as (K, V). -struct MapIterImpl<'m, 'a, K, V>(&'m Map<'a, K, V>, i32); +struct IterImpl<'m, 'a, K, V>(&'m Map<'a, K, V>, i32); -impl<'m, 'a, K, V> MapIterImpl<'m, 'a, K, V> { +impl<'m, 'a, K, V> IterImpl<'m, 'a, K, V> { fn new(map: &'m Map<'a, K, V>) -> Self { Self(map, -1) } } -impl<'m, 'a, K, V> Iterator for MapIterImpl<'m, 'a, K, V> { +impl<'m, 'a, K, V> Iterator for IterImpl<'m, 'a, K, V> { type Item = (u32, u32); fn next(&mut self) -> Option { diff --git a/src/set.rs b/src/set.rs index a59ded1..bff098c 100644 --- a/src/set.rs +++ b/src/set.rs @@ -1,3 +1,12 @@ +//! Set represents a mathematical set of integer values. +//! +//! While set in this module can be used as a general-purpose set in Rust code, it is recommended that you instead use +//! [`std::collections::BTreeSet`] or [`std::collections::HashSet`] as those are implemented directly in Rust and do not +//! rely on FFI to work. +//! +//! Sets are used in HarfBuzz in some non-shaping APIs to query certain sets of characters or glyphs, or other integer +//! values. + use std::{ any::TypeId, fmt, @@ -10,8 +19,6 @@ use std::{ use crate::{sys, AllocationError, Tag}; /// Set objects represent a mathematical set of integer values. -/// -/// Sets are used in non-shaping APIs to query certain sets of characters or glyphs, or other integer values. pub struct Set<'a, T>(InnerSet, PhantomData<(&'a (), T)>); impl Set<'static, T> { @@ -39,7 +46,7 @@ impl<'a, T> Set<'a, T> { /// elements that can be represented as `T`. This is especially evident when the set is over [`char`]s and invalid /// code points have been added with [`Self::insert_range`]. /// ``` - /// # use hb_subset::CharSet; + /// # use hb_subset::set::CharSet; /// # fn main() -> Result<(), Box> { /// let mut set = CharSet::new()?; /// set.insert_range('\u{D7FF}'..'\u{E000}'); // Add all surrogate pairs (and \u{D7FF} for technical reasons) @@ -164,7 +171,7 @@ where /// /// Will panic if `range` explicitly contains [`sys::HB_SET_VALUE_INVALID`]: /// ```should_panic - /// # use hb_subset::U32Set; + /// # use hb_subset::set::U32Set; /// # fn main() -> Result<(), Box> { /// U32Set::new()?.insert_range(u32::MAX-10..=u32::MAX); /// # Ok(()) @@ -172,7 +179,7 @@ where /// ``` /// These still work: /// ``` - /// # use hb_subset::U32Set; + /// # use hb_subset::set::U32Set; /// # fn main() -> Result<(), Box> { /// U32Set::new()?.insert_range(u32::MAX-10..); /// U32Set::new()?.insert_range(u32::MAX-10..u32::MAX); @@ -213,8 +220,8 @@ where /// Constructs an iterator over the set. #[doc(alias = "hb_set_next")] #[doc(alias = "hb_set_previous")] - pub fn iter(&self) -> SetIter<'_, 'a, T> { - SetIter(SetIterImpl::new(self).filter_map(|v| v.try_into().ok())) + pub fn iter(&self) -> Iter<'_, 'a, T> { + Iter(IterImpl::new(self).filter_map(|v| v.try_into().ok())) } } @@ -295,7 +302,7 @@ where T: TryFrom, { type Item = T; - type IntoIter = SetIter<'s, 'a, T>; + type IntoIter = Iter<'s, 'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() @@ -304,11 +311,11 @@ where /// Iterator over [`Set`]. /// -/// Use [`Set::iter`] to construct a [`SetIter`]. -pub struct SetIter<'s, 'a, T>(SetIterFilter<'s, 'a, T>); -type SetIterFilter<'s, 'a, T> = FilterMap, fn(u32) -> Option>; +/// Use [`Set::iter`] to construct a [`Iter`]. +pub struct Iter<'s, 'a, T>(IterFilter<'s, 'a, T>); +type IterFilter<'s, 'a, T> = FilterMap, fn(u32) -> Option>; -impl<'s, 'a, T> Iterator for SetIter<'s, 'a, T> +impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> where T: TryFrom, { @@ -319,7 +326,7 @@ where } } -impl<'s, 'a, T> DoubleEndedIterator for SetIter<'s, 'a, T> +impl<'s, 'a, T> DoubleEndedIterator for Iter<'s, 'a, T> where T: TryFrom, { @@ -328,15 +335,15 @@ where } } -impl<'s, 'a, T> FusedIterator for SetIter<'s, 'a, T> where T: TryFrom {} +impl<'s, 'a, T> FusedIterator for Iter<'s, 'a, T> where T: TryFrom {} -/// Actual implementation for [`SetIter`]. +/// Actual implementation for [`Iter`]. /// /// This implementation does not care whether the target type can or cannot represent the target type. It just returns -/// [`u32`], no matter what. [`SetIter`] is responsible to then filter out invalid values. -struct SetIterImpl<'s, 'a, T>(&'s Set<'a, T>, u32, u32); +/// [`u32`], no matter what. [`Iter`] is responsible to then filter out invalid values. +struct IterImpl<'s, 'a, T>(&'s Set<'a, T>, u32, u32); -impl<'s, 'a, T> SetIterImpl<'s, 'a, T> { +impl<'s, 'a, T> IterImpl<'s, 'a, T> { const LAST_VALUE: u32 = sys::HB_SET_VALUE_INVALID - 1; fn new(set: &'s Set<'a, T>) -> Self { #[allow(clippy::assertions_on_constants, clippy::absurd_extreme_comparisons)] @@ -350,7 +357,7 @@ impl<'s, 'a, T> SetIterImpl<'s, 'a, T> { } } -impl<'s, 'a, T> Iterator for SetIterImpl<'s, 'a, T> { +impl<'s, 'a, T> Iterator for IterImpl<'s, 'a, T> { type Item = u32; fn next(&mut self) -> Option { @@ -378,7 +385,7 @@ impl<'s, 'a, T> Iterator for SetIterImpl<'s, 'a, T> { } } -impl<'s, 'a, T> DoubleEndedIterator for SetIterImpl<'s, 'a, T> { +impl<'s, 'a, T> DoubleEndedIterator for IterImpl<'s, 'a, T> { fn next_back(&mut self) -> Option { match self.2 { 0 => { diff --git a/src/subset.rs b/src/subset.rs index 6ab5825..f1db2f5 100644 --- a/src/subset.rs +++ b/src/subset.rs @@ -1,6 +1,10 @@ use std::{marker::PhantomData, ptr::null_mut}; -use crate::{sys, AllocationError, CharSet, FontFace, Map, Set, SubsettingError, TagSet, U32Set}; +use crate::{ + map::Map, + set::{CharSet, Set, TagSet, U32Set}, + sys, AllocationError, FontFace, SubsettingError, +}; mod flags;