Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/servo/components/style/values/specified/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 9 kB image not shown  

Quelle  time.rs

  Sprache: Rust
 

/* 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 https://mozilla.org/MPL/2.0/. */


//! Specified time values.

use crate::derives::*;
use crate::parser::{Parse, ParserContext};
use crate::typed_om::{NumericValue, ToTyped, TypedValue, UnitValue};
use crate::values::computed::time::Time as ComputedTime;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::specified::calc::{CalcNode, CalcNumeric, Leaf};
use crate::values::tagged_numeric::{NumericUnion, Unpacked};
use crate::values::CSSFloat;
use crate::Zero;
use cssparser::{match_ignore_ascii_case, Parser, Token};
use std::fmt::{self, Write};
use style_traits::values::specified::AllowedNumericType;
use style_traits::{
    CssString, CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss,
};
use thin_vec::ThinVec;

/// A time unit.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u8)]
pub enum TimeUnit {
    /// `s`
    Second,
    /// `ms`
    Millisecond,
}

impl TimeUnit {
    /// Returns the time unit for the given string.
    #[inline]
    pub fn from_str(unit: &str) -> Result<Self, ()> {
        Ok(match_ignore_ascii_case! { unit,
            "s" => Self::Second,
            "ms" => Self::Millisecond,
            _ => return Err(())
        })
    }

    /// Returns this unit as a string.
    #[inline]
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Second => "s",
            Self::Millisecond => "ms",
        }
    }
}

/// A time value according to CSS-VALUES § 6.2.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
#[repr(C)]
pub struct NoCalcTime {
    unit: TimeUnit,
    value: CSSFloat,
}

impl NoCalcTime {
    /// Creates a time with the given unit and value (in that unit).
    #[inline]
    pub fn new(unit: TimeUnit, value: CSSFloat) -> Self {
        Self { unit, value }
    }

    /// Returns a time value that represents `seconds` seconds.
    #[inline]
    pub fn from_seconds(seconds: CSSFloat) -> Self {
        Self::new(TimeUnit::Second, seconds)
    }

    /// Returns the time in fractional seconds.
    #[inline]
    pub fn seconds(&self) -> CSSFloat {
        match self.unit {
            TimeUnit::Second => self.value,
            TimeUnit::Millisecond => self.value / 1000.0,
        }
    }

    /// Returns the unit of the time.
    #[inline]
    pub fn time_unit(&self) -> TimeUnit {
        self.unit
    }

    /// Returns the unit of the time as a string.
    #[inline]
    pub fn unit(&self) -> &'static str {
        self.unit.as_str()
    }

    /// Return the unitless, raw value.
    #[inline]
    pub fn unitless_value(&self) -> CSSFloat {
        self.value
    }

    /// Return the canonical unit for this value.
    pub fn canonical_unit(&self) -> Option<&'static str> {
        Some("s")
    }

    /// Convert this value to the specified unit, if possible.
    pub fn to(&self, unit: &str) -> Result<Self, ()> {
        let target = TimeUnit::from_str(unit)?;
        let value = match target {
            TimeUnit::Second => self.seconds(),
            TimeUnit::Millisecond => self.seconds() * 1000.0,
        };
        Ok(Self::new(target, value))
    }

    /// Parses a time according to CSS-VALUES § 6.2.
    pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Self, ()> {
        let unit = TimeUnit::from_str(unit)?;
        Ok(Self::new(unit, value))
    }
}

impl ToCss for NoCalcTime {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        crate::values::serialize_specified_dimension(
            self.unitless_value(),
            self.unit(),
            /* was_calc = */ false,
            dest,
        )
    }
}

impl ToComputedValue for NoCalcTime {
    type ComputedValue = ComputedTime;

    fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
        ComputedTime::from_seconds(self.seconds())
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        Self::from_seconds(computed.seconds())
    }
}

impl ToTyped for NoCalcTime {
    fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
        let numeric_value = NumericValue::Unit(UnitValue {
            value: self.unitless_value(),
            unit: CssString::from(self.unit()),
        });

        // https://drafts.css-houdini.org/css-typed-om-1/#reify-a-math-expression
        dest.push(TypedValue::Numeric(numeric_value));

        Ok(())
    }
}

impl SpecifiedValueInfo for NoCalcTime {}

/// A specified time value, either a plain value or a `calc()` expression.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub struct Time(NumericUnion<TimeUnit, f32, CalcNumeric>);

impl ToCss for Time {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        match self.0.unpack() {
            Unpacked::Inline(unit, value) => NoCalcTime::new(unit, value).to_css(dest),
            Unpacked::Boxed(calc) => calc.to_css(dest),
        }
    }
}

impl ToTyped for Time {
    fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
        match self.0.unpack() {
            Unpacked::Inline(unit, value) => NoCalcTime::new(unit, value).to_typed(dest),
            Unpacked::Boxed(calc) => calc.to_typed(dest),
        }
    }
}

impl SpecifiedValueInfo for Time {}

impl Time {
    /// Creates a time from a non-calc `NoCalcTime`.
    #[inline]
    pub fn new(time: NoCalcTime) -> Self {
        Self(NumericUnion::inline(time.unit, time.value))
    }

    /// Creates a time from a `calc()` expression.
    #[inline]
    pub fn new_calc(calc: Box<CalcNumeric>) -> Self {
        Self(NumericUnion::boxed(calc))
    }

    /// Returns a time value that represents `seconds` seconds.
    #[inline]
    pub fn from_seconds(seconds: CSSFloat) -> Self {
        Self::new(NoCalcTime::from_seconds(seconds))
    }

    /// Returns true if this is a `calc()` expression.
    #[inline]
    pub fn is_calc(&self) -> bool {
        self.0.is_boxed()
    }

    fn parse_with_clamping_mode<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
        clamping_mode: AllowedNumericType,
    ) -> Result<Self, ParseError<'i>> {
        use style_traits::ParsingMode;

        let location = input.current_source_location();
        match *input.next()? {
            // Note that we generally pass ParserContext to is_ok() to check
            // that the ParserMode of the ParserContext allows all numeric
            // values for SMIL regardless of clamping_mode, but in this Time
            // value case, the value does not animate for SMIL at all, so we use
            // ParsingMode::DEFAULT directly.
            Token::Dimension {
                value, ref unit, ..
            } if clamping_mode.is_ok(ParsingMode::DEFAULT, value) => {
                NoCalcTime::parse_dimension(value, unit)
                    .map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
                    .map(Self::new)
            },
            Token::Function(ref name) => {
                let function = CalcNode::math_function(context, name, location)?;
                CalcNode::parse_time(context, input, clamping_mode, function)
                    .map(Box::new)
                    .map(Self::new_calc)
            },
            ref t => return Err(location.new_unexpected_token_error(t.clone())),
        }
    }

    /// Parses a non-negative time value.
    pub fn parse_non_negative<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
    }
}

impl Zero for Time {
    #[inline]
    fn zero() -> Self {
        Self::from_seconds(0.0)
    }

    #[inline]
    fn is_zero(&self) -> bool {
        // The unit doesn't matter, i.e. `s` and `ms` are the same for zero.
        match self.0.unpack() {
            Unpacked::Inline(_, value) => value == 0.0,
            Unpacked::Boxed(_) => false,
        }
    }
}

impl ToComputedValue for Time {
    type ComputedValue = ComputedTime;

    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match self.0.unpack() {
            Unpacked::Inline(unit, value) => {
                NoCalcTime::new(unit, value).to_computed_value(context)
            },
            Unpacked::Boxed(calc) => {
                let value = calc.resolve(context, |result| match result {
                    Ok(Leaf::Time(t)) => t.seconds(),
                    _ => {
                        debug_assert!(false"Unexpected Time::Calc without resolved time");
                        f32::NAN
                    },
                });
                ComputedTime::from_seconds(
                    crate::values::normalize(value).min(f32::MAX).max(f32::MIN),
                )
            },
        }
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        Self::from_seconds(computed.seconds())
    }
}

impl Parse for Time {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
    }
}

Messung V0.5 in Prozent
C=89 H=100 G=94

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.