From 4399b9552f202416901562ed2137d925cc13f35c Mon Sep 17 00:00:00 2001 From: Daniel Olano <daniel@olanod.com> Date: Fri, 31 May 2024 12:12:53 +0200 Subject: [PATCH 1/5] Make create no_std compatible --- Cargo.toml | 2 ++ color/lib.rs | 6 +++--- src/color.rs | 2 +- src/cow_rc_str.rs | 7 ++++--- src/lib.rs | 4 +++- src/macros.rs | 4 ++-- src/parser.rs | 8 +++++--- src/rules_and_declarations.rs | 4 ++-- src/serializer.rs | 5 +++-- src/size_of_tests.rs | 4 ++-- src/tokenizer.rs | 7 +++++-- src/unicode_range.rs | 4 ++-- 12 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f783f19f..729a0396 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,10 +32,12 @@ inherits = "release" debug = true [features] +default = ["std"] bench = [] dummy_match_byte = [] # Useful for skipping tests when execution is slow, e.g., under miri skip_long_tests = [] +std = [] [workspace] members = [".", "./macros", "./color"] diff --git a/color/lib.rs b/color/lib.rs index 5b116c23..070a9524 100644 --- a/color/lib.rs +++ b/color/lib.rs @@ -1,7 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - +#![cfg_attr(not(test), no_std)] #![deny(missing_docs)] //! Fairly complete css-color implementation. @@ -11,13 +11,13 @@ #[cfg(test)] mod tests; +use core::f32::consts::PI; +use core::fmt; use cssparser::color::{ clamp_floor_256_f32, clamp_unit_f32, parse_hash_color, serialize_color_alpha, PredefinedColorSpace, OPAQUE, }; use cssparser::{match_ignore_ascii_case, CowRcStr, ParseError, Parser, ToCss, Token}; -use std::f32::consts::PI; -use std::fmt; /// Return the named color with the given name. /// diff --git a/src/color.rs b/src/color.rs index 978936e0..f220b80c 100644 --- a/src/color.rs +++ b/src/color.rs @@ -15,7 +15,7 @@ pub const OPAQUE: f32 = 1.0; use crate::{BasicParseError, Parser, ToCss, Token}; -use std::fmt; +use core::fmt; /// Clamp a 0..1 number to a 0..255 range to u8. /// diff --git a/src/cow_rc_str.rs b/src/cow_rc_str.rs index 03631f47..b220be93 100644 --- a/src/cow_rc_str.rs +++ b/src/cow_rc_str.rs @@ -2,9 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::borrow::{Borrow, Cow}; -use std::rc::Rc; -use std::{cmp, fmt, hash, marker, mem, ops, ptr, slice, str}; +use alloc::borrow::{Borrow, Cow}; +use alloc::rc::Rc; +use alloc::string::String; +use core::{cmp, fmt, hash, marker, mem, ops, ptr, slice, str}; /// A string that is either shared (heap-allocated and reference-counted) or borrowed. /// diff --git a/src/lib.rs b/src/lib.rs index dc44fb74..a74d6afc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - +#![cfg_attr(not(feature = "std"), no_std)] #![crate_name = "cssparser"] #![crate_type = "rlib"] #![cfg_attr(feature = "bench", feature(test))] @@ -67,6 +67,8 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser) #![recursion_limit = "200"] // For color::parse_color_keyword +extern crate alloc; + pub use crate::cow_rc_str::CowRcStr; pub use crate::from_bytes::{stylesheet_encoding, EncodingSupport}; #[doc(hidden)] diff --git a/src/macros.rs b/src/macros.rs index 67d83658..13fbd3d3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::mem::MaybeUninit; +use core::mem::MaybeUninit; /// Expands to a `match` expression with string patterns, /// matching case-insensitively in the ASCII range. @@ -191,7 +191,7 @@ pub fn _cssparser_internal_to_lowercase<'a>( // `buffer` was initialized to a copy of `input` // (which is `&str` so well-formed UTF-8) // then ASCII-lowercased (which preserves UTF-8 well-formedness): - unsafe { ::std::str::from_utf8_unchecked(buffer) } + unsafe { ::core::str::from_utf8_unchecked(buffer) } } Some( diff --git a/src/parser.rs b/src/parser.rs index 0a432912..84cf673c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,10 +4,11 @@ use crate::cow_rc_str::CowRcStr; use crate::tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer}; +use alloc::vec::Vec; +use core::fmt; +use core::ops::BitOr; +use core::ops::Range; use smallvec::SmallVec; -use std::fmt; -use std::ops::BitOr; -use std::ops::Range; /// A capture of the internal state of a `Parser` (including the position within the input), /// obtained from the `Parser::position` method. @@ -224,6 +225,7 @@ impl<E: fmt::Display> fmt::Display for ParseError<'_, E> { } } +#[cfg(feature = "std")] impl<E: fmt::Display + fmt::Debug> std::error::Error for ParseError<'_, E> {} /// The owned input for a parser. diff --git a/src/rules_and_declarations.rs b/src/rules_and_declarations.rs index 188e354e..b750f6a1 100644 --- a/src/rules_and_declarations.rs +++ b/src/rules_and_declarations.rs @@ -199,7 +199,7 @@ pub struct RuleBodyParser<'i, 't, 'a, P, I, E> { /// The parser given to `DeclarationListParser::new` pub parser: &'a mut P, - _phantom: std::marker::PhantomData<(I, E)>, + _phantom: core::marker::PhantomData<(I, E)>, } /// A parser for a rule body item. @@ -235,7 +235,7 @@ impl<'i, 't, 'a, P, I, E> RuleBodyParser<'i, 't, 'a, P, I, E> { Self { input, parser, - _phantom: std::marker::PhantomData, + _phantom: core::marker::PhantomData, } } } diff --git a/src/serializer.rs b/src/serializer.rs index 5df73954..e880ff0f 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::match_byte; +use alloc::string::String; +use core::fmt::{self, Write}; +use core::str; use dtoa_short::Notation; -use std::fmt::{self, Write}; -use std::str; use super::Token; diff --git a/src/size_of_tests.rs b/src/size_of_tests.rs index edd2b439..4b1fdcc9 100644 --- a/src/size_of_tests.rs +++ b/src/size_of_tests.rs @@ -9,7 +9,7 @@ macro_rules! size_of_test { ($testname: ident, $t: ty, $expected_min_size: expr, $expected_max_size: expr) => { #[test] fn $testname() { - let new = ::std::mem::size_of::<$t>(); + let new = ::core::mem::size_of::<$t>(); if new < $expected_min_size { panic!( "Your changes have decreased the stack size of {} from {} to {}. \ @@ -39,7 +39,7 @@ macro_rules! size_of_test { // Some of these assume 64-bit size_of_test!(token, Token, 32); -size_of_test!(std_cow_str, std::borrow::Cow<'static, str>, 24, 32); +size_of_test!(std_cow_str, alloc::borrow::Cow<'static, str>, 24, 32); size_of_test!(cow_rc_str, CowRcStr, 16); size_of_test!(tokenizer, crate::tokenizer::Tokenizer, 72); diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 2e86c66a..63269ecc 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -7,8 +7,11 @@ use self::Token::*; use crate::cow_rc_str::CowRcStr; use crate::parser::ParserState; -use std::char; -use std::ops::Range; +use alloc::borrow::ToOwned; +use alloc::string::String; +use alloc::vec::Vec; +use core::char; +use core::ops::Range; #[cfg(not(feature = "dummy_match_byte"))] use cssparser_macros::match_byte; diff --git a/src/unicode_range.rs b/src/unicode_range.rs index a4130ef0..ffa00442 100644 --- a/src/unicode_range.rs +++ b/src/unicode_range.rs @@ -6,8 +6,8 @@ use crate::tokenizer::Token; use crate::{BasicParseError, Parser, ToCss}; -use std::char; -use std::fmt; +use core::char; +use core::fmt; /// One contiguous range of code points. /// From 79312b1aec8d81bb5006538bbe469833fa1dbec7 Mon Sep 17 00:00:00 2001 From: boquanfu <boquanfu@tencent.com> Date: Fri, 7 Jun 2024 19:35:48 +0800 Subject: [PATCH 2/5] feat: complete no-std support --- Cargo.toml | 5 +++-- src/color.rs | 6 +++--- src/lib.rs | 1 + src/math.rs | 21 +++++++++++++++++++++ src/serializer.rs | 2 +- src/tokenizer.rs | 2 +- 6 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 src/math.rs diff --git a/Cargo.toml b/Cargo.toml index 729a0396..198387d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,10 @@ encoding_rs = "0.8" cssparser-macros = { path = "./macros", version = "0.6.1" } dtoa-short = "0.3" itoa = "1.0" -phf = { version = "0.11.2", features = ["macros"] } +phf = { version = "0.11.2", features = ["macros"], default-features = false } serde = { version = "1.0", features = ["derive"], optional = true } smallvec = "1.0" +libm = "0.2.8" [profile.profiling] inherits = "release" @@ -37,7 +38,7 @@ bench = [] dummy_match_byte = [] # Useful for skipping tests when execution is slow, e.g., under miri skip_long_tests = [] -std = [] +std = ["phf/std"] [workspace] members = [".", "./macros", "./color"] diff --git a/src/color.rs b/src/color.rs index f220b80c..6124d30d 100644 --- a/src/color.rs +++ b/src/color.rs @@ -41,7 +41,7 @@ pub fn clamp_unit_f32(val: f32) -> u8 { /// Round and clamp a single number to a u8. #[inline] pub fn clamp_floor_256_f32(val: f32) -> u8 { - val.round().clamp(0., 255.) as u8 + crate::math::f32_round(val).clamp(0., 255.) as u8 } /// Serialize the alpha copmonent of a color according to the specification. @@ -65,9 +65,9 @@ pub fn serialize_color_alpha( dest.write_str(if legacy_syntax { ", " } else { " / " })?; // Try first with two decimal places, then with three. - let mut rounded_alpha = (alpha * 100.).round() / 100.; + let mut rounded_alpha = crate::math::f32_round(alpha * 100.) / 100.; if clamp_unit_f32(rounded_alpha) != clamp_unit_f32(alpha) { - rounded_alpha = (alpha * 1000.).round() / 1000.; + rounded_alpha = crate::math::f32_round(alpha * 1000.) / 1000.; } rounded_alpha.to_css(dest) diff --git a/src/lib.rs b/src/lib.rs index a74d6afc..6e56ccfc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,7 @@ mod nth; mod parser; mod serializer; mod unicode_range; +mod math; #[cfg(test)] mod size_of_tests; diff --git a/src/math.rs b/src/math.rs new file mode 100644 index 00000000..2d9ff1c6 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,21 @@ + +pub(crate) fn f32_trunc(val: f32) -> f32 { + #[cfg(feature = "std")] + { val.round() } + #[cfg(not(feature = "std"))] + { libm::roundf(val) } +} + +pub(crate) fn f32_round(val: f32) -> f32 { + #[cfg(feature = "std")] + { val.round() } + #[cfg(not(feature = "std"))] + { libm::roundf(val) } +} + +pub(crate) fn f64_pow(a: f64, b: f64) -> f64 { + #[cfg(feature = "std")] + { f64::powf(a, b) } + #[cfg(not(feature = "std"))] + { libm::pow(a, b) } +} diff --git a/src/serializer.rs b/src/serializer.rs index e880ff0f..58b366c0 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -49,7 +49,7 @@ where dtoa_short::write(dest, value)? }; - if int_value.is_none() && value.fract() == 0. && !notation.decimal_point && !notation.scientific + if int_value.is_none() && value == crate::math::f32_trunc(value) && !notation.decimal_point && !notation.scientific { dest.write_str(".0")?; } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 63269ecc..23a214a0 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1083,7 +1083,7 @@ fn consume_numeric<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> { break; } } - value *= f64::powf(10., sign * exponent); + value *= crate::math::f64_pow(10., sign * exponent); } let int_value = if is_integer { From 2e0e98a84f9123e4df3677422874351a9f9154ad Mon Sep 17 00:00:00 2001 From: LastLeaf <bqfu@163.com> Date: Mon, 17 Jun 2024 11:10:54 +0800 Subject: [PATCH 3/5] fix: update dep:dtoa-short to be no-std compatible --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 198387d4..1e933556 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ encoding_rs = "0.8" [dependencies] cssparser-macros = { path = "./macros", version = "0.6.1" } -dtoa-short = "0.3" +dtoa-short = "0.3.5" itoa = "1.0" phf = { version = "0.11.2", features = ["macros"], default-features = false } serde = { version = "1.0", features = ["derive"], optional = true } From 806c2f91d0d16c61e9a06715bc59132baa956ffd Mon Sep 17 00:00:00 2001 From: LastLeaf <bqfu@163.com> Date: Mon, 17 Jun 2024 21:40:47 +0800 Subject: [PATCH 4/5] feat: no-std for cssparser-color --- color/Cargo.toml | 7 +++++-- color/lib.rs | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/color/Cargo.toml b/color/Cargo.toml index 47544815..dca31291 100644 --- a/color/Cargo.toml +++ b/color/Cargo.toml @@ -12,10 +12,13 @@ edition = "2021" path = "lib.rs" [dependencies] -cssparser = { path = ".." } -serde = { version = "1.0", features = ["derive"], optional = true } +cssparser = { path = "..", default-features = false } +serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } +libm = "0.2.8" [features] +default = ["std"] +std = ["cssparser/std", "serde/std"] serde = ["cssparser/serde", "dep:serde"] [dev-dependencies] diff --git a/color/lib.rs b/color/lib.rs index 070a9524..79903a5b 100644 --- a/color/lib.rs +++ b/color/lib.rs @@ -488,11 +488,18 @@ impl<'a> ToCss for ModernComponent<'a> { } } +fn f32_floor(val: f32) -> f32 { + #[cfg(feature = "std")] + { val.floor() } + #[cfg(not(feature = "std"))] + { libm::floorf(val) } +} + // Guaratees hue in [0..360) fn normalize_hue(hue: f32) -> f32 { // <https://drafts.csswg.org/css-values/#angles> // Subtract an integer before rounding, to avoid some rounding errors: - hue - 360.0 * (hue / 360.0).floor() + hue - 360.0 * f32_floor(hue / 360.0) } /// A color with red, green, blue, and alpha components, in a byte each. From 0d98d4611646f1ede0e37daa88012734a015e4bb Mon Sep 17 00:00:00 2001 From: Daniel Olano <daniel@olanod.com> Date: Thu, 7 Nov 2024 19:10:21 +0100 Subject: [PATCH 5/5] Add missing license and inline anotations --- src/math.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/math.rs b/src/math.rs index 2d9ff1c6..4cf18ea8 100644 --- a/src/math.rs +++ b/src/math.rs @@ -1,4 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#[inline] pub(crate) fn f32_trunc(val: f32) -> f32 { #[cfg(feature = "std")] { val.round() } @@ -6,6 +10,7 @@ pub(crate) fn f32_trunc(val: f32) -> f32 { { libm::roundf(val) } } +#[inline] pub(crate) fn f32_round(val: f32) -> f32 { #[cfg(feature = "std")] { val.round() } @@ -13,6 +18,7 @@ pub(crate) fn f32_round(val: f32) -> f32 { { libm::roundf(val) } } +#[inline] pub(crate) fn f64_pow(a: f64, b: f64) -> f64 { #[cfg(feature = "std")] { f64::powf(a, b) }