Skip to content

Commit

Permalink
Add named color iterators and remove phf macro dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
Ogeon committed Nov 16, 2024
1 parent 13c298d commit 0e84996
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 35 deletions.
2 changes: 2 additions & 0 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"


19 changes: 12 additions & 7 deletions codegen/src/named.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>> = phf::phf_map! {
#(#entries),*
};
pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb<u8>> = #phf_entries;
}
}
2 changes: 1 addition & 1 deletion no_std_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 4 additions & 3 deletions palette/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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"
Expand Down
5 changes: 4 additions & 1 deletion palette/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
Expand All @@ -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. <strike>Enables `named::from_str`, which maps name strings to colors.</strike>

### 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.
Expand Down
167 changes: 146 additions & 21 deletions palette/src/named.rs
Original file line number Diff line number Diff line change
@@ -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::<f32>::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::<f32>::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<crate::Srgb<u8>> {
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<u8>>,
}

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<u8>);

fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(&name, &color)| (name, color))
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl DoubleEndedIterator for Entries {
fn next_back(&mut self) -> Option<Self::Item> {
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<u8>>,
}

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::Item> {
self.iter.next().copied()
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl DoubleEndedIterator for Names {
fn next_back(&mut self) -> Option<Self::Item> {
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<u8>>,
}

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<u8>;

fn next(&mut self) -> Option<Self::Item> {
self.iter.next().copied()
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl DoubleEndedIterator for Colors {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().copied()
}
}

impl ExactSizeIterator for Colors {}

impl FusedIterator for Colors {}
Loading

0 comments on commit 0e84996

Please sign in to comment.