diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 606ca4c..00d8748 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,10 +40,11 @@ jobs: fail-fast: false matrix: os: [macos-latest, windows-latest] - toolchain: [stable] + # TODO: use stable once GATs reach stable + toolchain: [beta] include: - os: ubuntu-latest - toolchain: "1.58.0" + toolchain: "1.65.0" - os: ubuntu-latest toolchain: beta diff --git a/Cargo.toml b/Cargo.toml index 06d115b..cf41739 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,9 +30,6 @@ harfbuzz = ["harfbuzz_rs"] # Enable Markdown parsing markdown = ["pulldown-cmark"] -# Use Generic Associated Types (experimental) -gat = [] - # Serialization is optionally supported for some types: # serde diff --git a/README.md b/README.md index a1fdefe..7e66f6c 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ Non-pure-Rust alternatives include [font-kit](https://crates.io/crates/font-kit) and [piet](https://crates.io/crates/piet) among others. +MSRV +--- + +The Minium Supported Rust Version is 1.65.0. + + Contributing -------- diff --git a/src/fonts/library.rs b/src/fonts/library.rs index b90f228..d7538e6 100644 --- a/src/fonts/library.rs +++ b/src/fonts/library.rs @@ -130,6 +130,9 @@ impl<'a> FaceStore<'a> { #[derive(Default)] struct FaceList { + // Safety: unsafe code depends on entries never moving (hence the otherwise + // redundant use of Box). See e.g. FontLibrary::get_face(). + #[allow(clippy::vec_box)] faces: Vec>>, // These are vec-maps. Why? Because length should be short. path_hash: Vec<(u64, FaceId)>, diff --git a/src/fonts/selector.rs b/src/fonts/selector.rs index 5e7d437..3e8936d 100644 --- a/src/fonts/selector.rs +++ b/src/fonts/selector.rs @@ -38,7 +38,7 @@ enum State { fn to_uppercase<'a>(c: Cow<'a, str>) -> Cow<'a, str> { match c { Cow::Borrowed(b) if !b.chars().any(|c| c.is_lowercase()) => Cow::Borrowed(b), - c => Cow::Owned(c.to_owned().to_uppercase()), + c => Cow::Owned(c.to_uppercase()), } } diff --git a/src/format.rs b/src/format.rs index b652810..da0a77b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -21,15 +21,7 @@ pub use markdown::{Error as MarkdownError, Markdown}; /// /// Any `F: FormattableText` automatically support [`FormattableTextDyn`]. /// Implement either this or [`FormattableTextDyn`], not both. -/// -/// This trait can only be written as intended using Generic Associated Types -/// (`gat`, unstable nightly feature), thus `font_tokens` has a different -/// signature with/without feature `gat` and the associated type -/// `FontTokenIter` is only present with feature `gat`. pub trait FormattableText: std::fmt::Debug { - #[cfg_attr(doc_cfg, doc(cfg(feature = "gat")))] - #[cfg(feature = "gat")] - // TODO: rename → Iter type FontTokenIter<'a>: Iterator where Self: 'a; @@ -53,20 +45,8 @@ pub trait FormattableText: std::fmt::Debug { /// The `dpem` parameter is font size as in [`crate::Environment`]. /// /// For plain text this iterator will be empty. - #[cfg(feature = "gat")] fn font_tokens<'a>(&'a self, dpem: f32) -> Self::FontTokenIter<'a>; - /// Construct an iterator over formatting items - /// - /// It is expected that [`FontToken::start`] of yielded items is strictly - /// increasing; if not, formatting may not be applied correctly. - /// - /// The `dpem` parameter is font size as in [`crate::Environment`]. - /// - /// For plain text this iterator will be empty. - #[cfg(not(feature = "gat"))] - fn font_tokens(&self, dpem: f32) -> OwningVecIter; - /// Get the sequence of effect tokens /// /// This method has some limitations: (1) it may only return a reference to @@ -117,7 +97,6 @@ pub trait FormattableTextDyn: std::fmt::Debug { fn effect_tokens(&self) -> &[Effect<()>]; } -// #[cfg(feature = "gat")] impl FormattableTextDyn for F { fn clone_boxed(&self) -> Box { Box::new(self.clone()) @@ -132,14 +111,7 @@ impl FormattableTextDyn for F { fn font_tokens(&self, dpem: f32) -> OwningVecIter { let iter = FormattableText::font_tokens(self, dpem); - #[cfg(feature = "gat")] - { - OwningVecIter::new(iter.collect()) - } - #[cfg(not(feature = "gat"))] - { - iter - } + OwningVecIter::new(iter.collect()) } fn effect_tokens(&self) -> &[Effect<()>] { @@ -148,11 +120,9 @@ impl FormattableTextDyn for F { } impl<'t> FormattableText for &'t dyn FormattableTextDyn { - #[cfg(feature = "gat")] - type FontTokenIter<'a> + type FontTokenIter<'a> = OwningVecIter where - Self: 'a, - = OwningVecIter; + Self: 'a,; #[inline] fn str_len(&self) -> usize { diff --git a/src/format/markdown.rs b/src/format/markdown.rs index 8f60722..cc80eea 100644 --- a/src/format/markdown.rs +++ b/src/format/markdown.rs @@ -8,8 +8,6 @@ use super::{EditableText, FontToken, FormattableText}; use crate::conv::to_u32; use crate::fonts::{self, FontId, FontSelector, Style, Weight}; -#[cfg(not(feature = "gat"))] -use crate::OwningVecIter; use crate::{Effect, EffectFlags}; use pulldown_cmark::{Event, HeadingLevel, Tag}; use std::fmt::Write; @@ -108,7 +106,6 @@ impl<'a> ExactSizeIterator for FontTokenIter<'a> {} impl<'a> FusedIterator for FontTokenIter<'a> {} impl FormattableText for Markdown { - #[cfg(feature = "gat")] type FontTokenIter<'a> = FontTokenIter<'a>; #[inline] @@ -116,17 +113,10 @@ impl FormattableText for Markdown { &self.text } - #[cfg(feature = "gat")] #[inline] fn font_tokens<'a>(&'a self, dpem: f32) -> Self::FontTokenIter<'a> { FontTokenIter::new(&self.fmt, dpem) } - #[cfg(not(feature = "gat"))] - #[inline] - fn font_tokens(&self, dpem: f32) -> OwningVecIter { - let iter = FontTokenIter::new(&self.fmt, dpem); - OwningVecIter::new(iter.collect()) - } fn effect_tokens(&self) -> &[Effect<()>] { &self.effects diff --git a/src/format/plain.rs b/src/format/plain.rs index 15b1e73..3b63887 100644 --- a/src/format/plain.rs +++ b/src/format/plain.rs @@ -7,28 +7,19 @@ use super::{EditableText, FontToken, FormattableText}; use crate::Effect; -#[cfg(not(feature = "gat"))] -use crate::OwningVecIter; impl<'t> FormattableText for &'t str { - #[cfg(feature = "gat")] - type FontTokenIter<'a> + type FontTokenIter<'a> = std::iter::Empty where - Self: 'a, - = std::iter::Empty; + Self: 'a; fn as_str(&self) -> &str { self } - #[cfg(feature = "gat")] fn font_tokens<'a>(&'a self, _: f32) -> Self::FontTokenIter<'a> { std::iter::empty() } - #[cfg(not(feature = "gat"))] - fn font_tokens(&self, _: f32) -> OwningVecIter { - OwningVecIter::new(Vec::new()) - } fn effect_tokens(&self) -> &[Effect<()>] { &[] @@ -36,21 +27,15 @@ impl<'t> FormattableText for &'t str { } impl FormattableText for String { - #[cfg(feature = "gat")] type FontTokenIter<'a> = std::iter::Empty; fn as_str(&self) -> &str { self } - #[cfg(feature = "gat")] fn font_tokens<'a>(&'a self, _: f32) -> Self::FontTokenIter<'a> { std::iter::empty() } - #[cfg(not(feature = "gat"))] - fn font_tokens(&self, _: f32) -> OwningVecIter { - OwningVecIter::new(Vec::new()) - } fn effect_tokens(&self) -> &[Effect<()>] { &[] diff --git a/src/lib.rs b/src/lib.rs index 5140e0c..460598c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,6 @@ //! [`format`]: mod@format #![cfg_attr(doc_cfg, feature(doc_cfg))] -#![cfg_attr(feature = "gat", feature(generic_associated_types))] #![allow(clippy::len_zero)] #![allow(clippy::type_complexity)] #![allow(clippy::unit_arg)]