diff --git a/Cargo.toml b/Cargo.toml index f783f19f..1e933556 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,21 +21,24 @@ 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"] } +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" 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 = ["phf/std"] [workspace] members = [".", "./macros", "./color"] 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 5b116c23..79903a5b 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. /// @@ -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 { // // 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. diff --git a/src/color.rs b/src/color.rs index 978936e0..6124d30d 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. /// @@ -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/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..6e56ccfc 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)] @@ -101,6 +103,7 @@ mod nth; mod parser; mod serializer; mod unicode_range; +mod math; #[cfg(test)] mod size_of_tests; 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/math.rs b/src/math.rs new file mode 100644 index 00000000..4cf18ea8 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,27 @@ +/* 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() } + #[cfg(not(feature = "std"))] + { libm::roundf(val) } +} + +#[inline] +pub(crate) fn f32_round(val: f32) -> f32 { + #[cfg(feature = "std")] + { val.round() } + #[cfg(not(feature = "std"))] + { libm::roundf(val) } +} + +#[inline] +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/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 fmt::Display for ParseError<'_, E> { } } +#[cfg(feature = "std")] impl 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..58b366c0 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; @@ -48,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/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..23a214a0 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; @@ -1080,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 { 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. ///