From 0e8499672aa58e033c46d1265a5014e71417455b Mon Sep 17 00:00:00 2001 From: Erik Hedvall Date: Sat, 16 Nov 2024 16:11:37 +0100 Subject: [PATCH] Add named color iterators and remove phf macro dependency --- codegen/Cargo.toml | 2 + codegen/src/named.rs | 19 ++-- no_std_test/Cargo.toml | 2 +- palette/Cargo.toml | 7 +- palette/README.md | 5 +- palette/src/named.rs | 167 +++++++++++++++++++++++++++---- palette/src/named/codegen.rs | 187 ++++++++++++++++++++++++++++++++++- 7 files changed, 354 insertions(+), 35 deletions(-) diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 14eece447..491e6056d 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -13,5 +13,7 @@ publish = false anyhow = "1.0.86" proc-macro2 = "1.0.86" quote = "1.0.37" +phf = "0.11.2" +phf_codegen = "0.11.2" diff --git a/codegen/src/named.rs b/codegen/src/named.rs index dd66149a7..becc4a80e 100644 --- a/codegen/src/named.rs +++ b/codegen/src/named.rs @@ -101,14 +101,19 @@ fn build_colors(colors: &[ColorEntry]) -> TokenStream { } fn build_from_str(entries: &[ColorEntry]) -> TokenStream { - let entries = entries - .iter() - .map(|ColorEntry { name, constant, .. }| quote! {#name => #constant}); + let mut map = phf_codegen::Map::new(); + + for entry in entries { + map.entry(&*entry.name, &entry.constant.to_string()); + } + + let phf_entries: TokenStream = map + .build() + .to_string() + .parse() + .expect("phf should generate a valid token stream"); quote! { - #[cfg(feature = "named_from_str")] - pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb> = phf::phf_map! { - #(#entries),* - }; + pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb> = #phf_entries; } } diff --git a/no_std_test/Cargo.toml b/no_std_test/Cargo.toml index b7f474309..0f0249b06 100644 --- a/no_std_test/Cargo.toml +++ b/no_std_test/Cargo.toml @@ -16,7 +16,7 @@ bench = false [features] nightly = [] # Avoids getting these features included in other packages in the same workspace. -all_features = ["palette/libm", "palette/named_from_str"] +all_features = ["palette/libm", "palette/named"] [dependencies.libc] version = "0.2" diff --git a/palette/Cargo.toml b/palette/Cargo.toml index 094c6c188..383bc8954 100644 --- a/palette/Cargo.toml +++ b/palette/Cargo.toml @@ -28,14 +28,16 @@ rust-version = "1.61.0" [features] default = ["named_from_str", "std", "approx"] -named_from_str = ["named", "phf"] -named = [] +named = ["phf"] random = ["rand"] serializing = ["serde", "std"] find-crate = ["palette_derive/find-crate"] std = ["alloc", "approx?/std"] alloc = [] +# Deprecated. Alias for `"named"`. +named_from_str = ["named"] + [lib] bench = false @@ -49,7 +51,6 @@ libm = { version = "0.2.1", default-features = false, optional = true } version = "0.11.0" optional = true default-features = false -features = ["macros"] [dependencies.rand] version = "0.8" diff --git a/palette/README.md b/palette/README.md index 68633bc37..173e10f9d 100644 --- a/palette/README.md +++ b/palette/README.md @@ -42,7 +42,6 @@ features = ["libm"] # Uses libm instead of std for floating point math These features are enabled by default: * `"named"` - Enables color constants, located in the `named` module. -* `"named_from_str"` - Enables `named::from_str`, which maps name strings to colors. * `"std"` - Enables use of the standard library. Also enables `"alloc"`. * `"alloc"` - Enables implementations for allocating types, such as `Vec` or `Box`. * `"approx"` - Enables approximate comparison using [`approx`]. @@ -56,6 +55,10 @@ These features are disabled by default: * `"wide"` - Enables support for using SIMD types from [`wide`]. * `"find-crate"` - Enables derives to find the `palette` crate when it's renamed in `Cargo.toml`. +These features have been deprecated: + +* `"named_from_str"` - Alias for `"named"`, still enabled by default. Enables `named::from_str`, which maps name strings to colors. + ### Using palette in an embedded environment Palette supports `#![no_std]` environments by disabling the `"std"` feature. It uses [`libm`], via the `"libm"` feature, to provide the floating-point operations that are typically in `std`, and the `"alloc"` feature to provide features that use allocating types. However, serializing with `serde` is not available without the standard library. diff --git a/palette/src/named.rs b/palette/src/named.rs index 7309aa0b2..5ac0da1ea 100644 --- a/palette/src/named.rs +++ b/palette/src/named.rs @@ -1,39 +1,164 @@ -//! A collection of named color constants. Can be toggled with the `"named"` and -//! `"named_from_str"` Cargo features. +//! A collection of named color constants. Can be toggled with the `"named"` +//! Cargo features. //! //! They are taken from the [SVG keyword -//! colors](https://www.w3.org/TR/SVG11/types.html#ColorKeywords) (same as in -//! CSS3) and they can be used as if they were pixel values: +//! colors](https://www.w3.org/TR/SVG11/types.html#ColorKeywords). These are +//! also part of the CSS3 standard. //! //! ``` //! use palette::Srgb; //! use palette::named; //! //! //From constant -//! let from_const = Srgb::::from_format(named::OLIVE).into_linear(); -#![cfg_attr(feature = "named_from_str", doc = "")] -#![cfg_attr(feature = "named_from_str", doc = "//From name string")] -#![cfg_attr( - feature = "named_from_str", - doc = "let olive = named::from_str(\"olive\").expect(\"unknown color\");" -)] -#![cfg_attr( - feature = "named_from_str", - doc = "let from_str = Srgb::::from_format(olive).into_linear();" -)] -#![cfg_attr(feature = "named_from_str", doc = "")] -#![cfg_attr(feature = "named_from_str", doc = "assert_eq!(from_const, from_str);")] +//! let from_const = named::OLIVE; +//! +//! //From name string +//! let from_str = named::from_str("olive").expect("unknown color"); +//! +//! assert_eq!(from_const, from_str); //! ``` +use core::{fmt, iter::FusedIterator}; + pub use codegen::*; mod codegen; -/// Get a SVG/CSS3 color by name. Can be toggled with the `"named_from_str"` -/// Cargo feature. +/// Get an SVG/CSS3 color by name. /// /// The names are the same as the constants, but lower case. -#[cfg(feature = "named_from_str")] pub fn from_str(name: &str) -> Option> { - COLORS.get(name).cloned() + COLORS.get(name).copied() +} + +/// Get an iterator over all SVG/CSS3 names and colors in arbitrary order. +/// +/// ``` +/// use palette::Srgb; +/// +/// let red = Srgb::new(255u8, 0, 0); +/// +/// let red_entry = palette::named::entries().find(|(name, color)| *color == red); +/// assert_eq!(red_entry, Some(("red", red))); +/// ``` +pub fn entries() -> Entries { + Entries { + iter: COLORS.entries(), + } +} + +/// Get an iterator over all SVG/CSS3 color names in arbitrary order. +pub fn names() -> Names { + Names { + iter: COLORS.keys(), + } +} + +/// Get an iterator over all SVG/CSS3 color values in arbitrary order. +pub fn colors() -> Colors { + Colors { + iter: COLORS.values(), + } +} + +/// An iterator over SVG/CSS3 color entries. +#[derive(Clone)] +pub struct Entries { + iter: phf::map::Entries<'static, &'static str, crate::Srgb>, +} + +impl fmt::Debug for Entries { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.fmt(f) + } +} + +impl Iterator for Entries { + type Item = (&'static str, crate::Srgb); + + fn next(&mut self) -> Option { + self.iter.next().map(|(&name, &color)| (name, color)) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for Entries { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|(&name, &color)| (name, color)) + } +} + +impl ExactSizeIterator for Entries {} + +impl FusedIterator for Entries {} + +/// An iterator over SVG/CSS3 color names. +#[derive(Clone)] +pub struct Names { + iter: phf::map::Keys<'static, &'static str, crate::Srgb>, +} + +impl fmt::Debug for Names { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.fmt(f) + } +} + +impl Iterator for Names { + type Item = &'static str; + + fn next(&mut self) -> Option { + self.iter.next().copied() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for Names { + fn next_back(&mut self) -> Option { + self.iter.next_back().copied() + } +} + +impl ExactSizeIterator for Names {} + +impl FusedIterator for Names {} + +/// An iterator over SVG/CSS3 color values. +#[derive(Clone)] +pub struct Colors { + iter: phf::map::Values<'static, &'static str, crate::Srgb>, +} + +impl fmt::Debug for Colors { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.fmt(f) + } +} + +impl Iterator for Colors { + type Item = crate::Srgb; + + fn next(&mut self) -> Option { + self.iter.next().copied() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for Colors { + fn next_back(&mut self) -> Option { + self.iter.next_back().copied() + } } + +impl ExactSizeIterator for Colors {} + +impl FusedIterator for Colors {} diff --git a/palette/src/named/codegen.rs b/palette/src/named/codegen.rs index 1211787c0..e36466638 100644 --- a/palette/src/named/codegen.rs +++ b/palette/src/named/codegen.rs @@ -299,6 +299,189 @@ pub const YELLOW: crate::rgb::Srgb = crate::rgb::Srgb::new(255u8, 255u8, 0u8 #[doc = "
"] pub const YELLOWGREEN: crate::rgb::Srgb = crate::rgb::Srgb::new(154u8, 205u8, 50u8); -#[cfg(feature = "named_from_str")] -pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb> = phf::phf_map! { "aliceblue" => ALICEBLUE , "antiquewhite" => ANTIQUEWHITE , "aqua" => AQUA , "aquamarine" => AQUAMARINE , "azure" => AZURE , "beige" => BEIGE , "bisque" => BISQUE , "black" => BLACK , "blanchedalmond" => BLANCHEDALMOND , "blue" => BLUE , "blueviolet" => BLUEVIOLET , "brown" => BROWN , "burlywood" => BURLYWOOD , "cadetblue" => CADETBLUE , "chartreuse" => CHARTREUSE , "chocolate" => CHOCOLATE , "coral" => CORAL , "cornflowerblue" => CORNFLOWERBLUE , "cornsilk" => CORNSILK , "crimson" => CRIMSON , "cyan" => CYAN , "darkblue" => DARKBLUE , "darkcyan" => DARKCYAN , "darkgoldenrod" => DARKGOLDENROD , "darkgray" => DARKGRAY , "darkgreen" => DARKGREEN , "darkgrey" => DARKGREY , "darkkhaki" => DARKKHAKI , "darkmagenta" => DARKMAGENTA , "darkolivegreen" => DARKOLIVEGREEN , "darkorange" => DARKORANGE , "darkorchid" => DARKORCHID , "darkred" => DARKRED , "darksalmon" => DARKSALMON , "darkseagreen" => DARKSEAGREEN , "darkslateblue" => DARKSLATEBLUE , "darkslategray" => DARKSLATEGRAY , "darkslategrey" => DARKSLATEGREY , "darkturquoise" => DARKTURQUOISE , "darkviolet" => DARKVIOLET , "deeppink" => DEEPPINK , "deepskyblue" => DEEPSKYBLUE , "dimgray" => DIMGRAY , "dimgrey" => DIMGREY , "dodgerblue" => DODGERBLUE , "firebrick" => FIREBRICK , "floralwhite" => FLORALWHITE , "forestgreen" => FORESTGREEN , "fuchsia" => FUCHSIA , "gainsboro" => GAINSBORO , "ghostwhite" => GHOSTWHITE , "gold" => GOLD , "goldenrod" => GOLDENROD , "gray" => GRAY , "grey" => GREY , "green" => GREEN , "greenyellow" => GREENYELLOW , "honeydew" => HONEYDEW , "hotpink" => HOTPINK , "indianred" => INDIANRED , "indigo" => INDIGO , "ivory" => IVORY , "khaki" => KHAKI , "lavender" => LAVENDER , "lavenderblush" => LAVENDERBLUSH , "lawngreen" => LAWNGREEN , "lemonchiffon" => LEMONCHIFFON , "lightblue" => LIGHTBLUE , "lightcoral" => LIGHTCORAL , "lightcyan" => LIGHTCYAN , "lightgoldenrodyellow" => LIGHTGOLDENRODYELLOW , "lightgray" => LIGHTGRAY , "lightgreen" => LIGHTGREEN , "lightgrey" => LIGHTGREY , "lightpink" => LIGHTPINK , "lightsalmon" => LIGHTSALMON , "lightseagreen" => LIGHTSEAGREEN , "lightskyblue" => LIGHTSKYBLUE , "lightslategray" => LIGHTSLATEGRAY , "lightslategrey" => LIGHTSLATEGREY , "lightsteelblue" => LIGHTSTEELBLUE , "lightyellow" => LIGHTYELLOW , "lime" => LIME , "limegreen" => LIMEGREEN , "linen" => LINEN , "magenta" => MAGENTA , "maroon" => MAROON , "mediumaquamarine" => MEDIUMAQUAMARINE , "mediumblue" => MEDIUMBLUE , "mediumorchid" => MEDIUMORCHID , "mediumpurple" => MEDIUMPURPLE , "mediumseagreen" => MEDIUMSEAGREEN , "mediumslateblue" => MEDIUMSLATEBLUE , "mediumspringgreen" => MEDIUMSPRINGGREEN , "mediumturquoise" => MEDIUMTURQUOISE , "mediumvioletred" => MEDIUMVIOLETRED , "midnightblue" => MIDNIGHTBLUE , "mintcream" => MINTCREAM , "mistyrose" => MISTYROSE , "moccasin" => MOCCASIN , "navajowhite" => NAVAJOWHITE , "navy" => NAVY , "oldlace" => OLDLACE , "olive" => OLIVE , "olivedrab" => OLIVEDRAB , "orange" => ORANGE , "orangered" => ORANGERED , "orchid" => ORCHID , "palegoldenrod" => PALEGOLDENROD , "palegreen" => PALEGREEN , "paleturquoise" => PALETURQUOISE , "palevioletred" => PALEVIOLETRED , "papayawhip" => PAPAYAWHIP , "peachpuff" => PEACHPUFF , "peru" => PERU , "pink" => PINK , "plum" => PLUM , "powderblue" => POWDERBLUE , "purple" => PURPLE , "rebeccapurple" => REBECCAPURPLE , "red" => RED , "rosybrown" => ROSYBROWN , "royalblue" => ROYALBLUE , "saddlebrown" => SADDLEBROWN , "salmon" => SALMON , "sandybrown" => SANDYBROWN , "seagreen" => SEAGREEN , "seashell" => SEASHELL , "sienna" => SIENNA , "silver" => SILVER , "skyblue" => SKYBLUE , "slateblue" => SLATEBLUE , "slategray" => SLATEGRAY , "slategrey" => SLATEGREY , "snow" => SNOW , "springgreen" => SPRINGGREEN , "steelblue" => STEELBLUE , "tan" => TAN , "teal" => TEAL , "thistle" => THISTLE , "tomato" => TOMATO , "turquoise" => TURQUOISE , "violet" => VIOLET , "wheat" => WHEAT , "white" => WHITE , "whitesmoke" => WHITESMOKE , "yellow" => YELLOW , "yellowgreen" => YELLOWGREEN }; +pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb> = ::phf::Map { + key: 12913932095322966823, + disps: &[ + (0, 28), + (4, 71), + (0, 126), + (2, 94), + (2, 43), + (0, 12), + (0, 4), + (0, 3), + (1, 10), + (3, 47), + (0, 10), + (0, 144), + (0, 3), + (0, 106), + (9, 89), + (1, 0), + (2, 22), + (0, 75), + (0, 0), + (21, 111), + (0, 5), + (1, 4), + (0, 6), + (0, 140), + (0, 123), + (0, 53), + (7, 109), + (0, 72), + (21, 89), + (11, 84), + ], + entries: &[ + ("lightgray", LIGHTGRAY), + ("gainsboro", GAINSBORO), + ("deeppink", DEEPPINK), + ("blueviolet", BLUEVIOLET), + ("orange", ORANGE), + ("orangered", ORANGERED), + ("brown", BROWN), + ("mistyrose", MISTYROSE), + ("seagreen", SEAGREEN), + ("indianred", INDIANRED), + ("darkgrey", DARKGREY), + ("slateblue", SLATEBLUE), + ("lightgrey", LIGHTGREY), + ("sandybrown", SANDYBROWN), + ("green", GREEN), + ("cornsilk", CORNSILK), + ("lavender", LAVENDER), + ("darkkhaki", DARKKHAKI), + ("tan", TAN), + ("steelblue", STEELBLUE), + ("darkgreen", DARKGREEN), + ("lightyellow", LIGHTYELLOW), + ("magenta", MAGENTA), + ("teal", TEAL), + ("navy", NAVY), + ("mediumaquamarine", MEDIUMAQUAMARINE), + ("linen", LINEN), + ("pink", PINK), + ("plum", PLUM), + ("lightsalmon", LIGHTSALMON), + ("salmon", SALMON), + ("violet", VIOLET), + ("mediumorchid", MEDIUMORCHID), + ("rosybrown", ROSYBROWN), + ("azure", AZURE), + ("palevioletred", PALEVIOLETRED), + ("lightcyan", LIGHTCYAN), + ("wheat", WHEAT), + ("darkblue", DARKBLUE), + ("olive", OLIVE), + ("lightcoral", LIGHTCORAL), + ("saddlebrown", SADDLEBROWN), + ("peru", PERU), + ("mediumvioletred", MEDIUMVIOLETRED), + ("forestgreen", FORESTGREEN), + ("sienna", SIENNA), + ("turquoise", TURQUOISE), + ("dimgrey", DIMGREY), + ("palegoldenrod", PALEGOLDENROD), + ("honeydew", HONEYDEW), + ("cyan", CYAN), + ("blue", BLUE), + ("palegreen", PALEGREEN), + ("darkgoldenrod", DARKGOLDENROD), + ("darkred", DARKRED), + ("rebeccapurple", REBECCAPURPLE), + ("aqua", AQUA), + ("lightseagreen", LIGHTSEAGREEN), + ("red", RED), + ("coral", CORAL), + ("slategray", SLATEGRAY), + ("orchid", ORCHID), + ("lightgreen", LIGHTGREEN), + ("olivedrab", OLIVEDRAB), + ("darkmagenta", DARKMAGENTA), + ("deepskyblue", DEEPSKYBLUE), + ("cadetblue", CADETBLUE), + ("tomato", TOMATO), + ("khaki", KHAKI), + ("darkorchid", DARKORCHID), + ("lightblue", LIGHTBLUE), + ("darksalmon", DARKSALMON), + ("limegreen", LIMEGREEN), + ("yellowgreen", YELLOWGREEN), + ("gold", GOLD), + ("grey", GREY), + ("silver", SILVER), + ("dodgerblue", DODGERBLUE), + ("papayawhip", PAPAYAWHIP), + ("midnightblue", MIDNIGHTBLUE), + ("cornflowerblue", CORNFLOWERBLUE), + ("burlywood", BURLYWOOD), + ("ghostwhite", GHOSTWHITE), + ("thistle", THISTLE), + ("darkslateblue", DARKSLATEBLUE), + ("lightsteelblue", LIGHTSTEELBLUE), + ("darkcyan", DARKCYAN), + ("powderblue", POWDERBLUE), + ("yellow", YELLOW), + ("lightskyblue", LIGHTSKYBLUE), + ("dimgray", DIMGRAY), + ("ivory", IVORY), + ("goldenrod", GOLDENROD), + ("seashell", SEASHELL), + ("aliceblue", ALICEBLUE), + ("fuchsia", FUCHSIA), + ("lightpink", LIGHTPINK), + ("darkslategrey", DARKSLATEGREY), + ("mediumpurple", MEDIUMPURPLE), + ("mediumblue", MEDIUMBLUE), + ("lightgoldenrodyellow", LIGHTGOLDENRODYELLOW), + ("antiquewhite", ANTIQUEWHITE), + ("aquamarine", AQUAMARINE), + ("whitesmoke", WHITESMOKE), + ("royalblue", ROYALBLUE), + ("lightslategrey", LIGHTSLATEGREY), + ("greenyellow", GREENYELLOW), + ("darkseagreen", DARKSEAGREEN), + ("floralwhite", FLORALWHITE), + ("blanchedalmond", BLANCHEDALMOND), + ("slategrey", SLATEGREY), + ("snow", SNOW), + ("darkslategray", DARKSLATEGRAY), + ("skyblue", SKYBLUE), + ("indigo", INDIGO), + ("firebrick", FIREBRICK), + ("darkolivegreen", DARKOLIVEGREEN), + ("mediumslateblue", MEDIUMSLATEBLUE), + ("darkgray", DARKGRAY), + ("lawngreen", LAWNGREEN), + ("white", WHITE), + ("mediumturquoise", MEDIUMTURQUOISE), + ("springgreen", SPRINGGREEN), + ("crimson", CRIMSON), + ("mediumseagreen", MEDIUMSEAGREEN), + ("lemonchiffon", LEMONCHIFFON), + ("navajowhite", NAVAJOWHITE), + ("lightslategray", LIGHTSLATEGRAY), + ("moccasin", MOCCASIN), + ("chocolate", CHOCOLATE), + ("maroon", MAROON), + ("paleturquoise", PALETURQUOISE), + ("oldlace", OLDLACE), + ("black", BLACK), + ("darkviolet", DARKVIOLET), + ("gray", GRAY), + ("lime", LIME), + ("lavenderblush", LAVENDERBLUSH), + ("mintcream", MINTCREAM), + ("peachpuff", PEACHPUFF), + ("hotpink", HOTPINK), + ("beige", BEIGE), + ("chartreuse", CHARTREUSE), + ("bisque", BISQUE), + ("darkorange", DARKORANGE), + ("darkturquoise", DARKTURQUOISE), + ("mediumspringgreen", MEDIUMSPRINGGREEN), + ("purple", PURPLE), + ], +};