lewp_css/domain/numbers/
css_number.rs

1// This file is part of css. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT. No part of predicator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
2// Copyright © 2017 The developers of css. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT.
3
4use {
5    super::CssNumberConversionError::*,
6    crate::{
7        domain::{
8            numbers::{CssNumberConversionError, CssNumberNewType},
9            units::{AppUnitsPer, Unit},
10        },
11        CustomParseError,
12    },
13    cssparser::{ParseError, ToCss},
14    std::{
15        fmt::{Debug, Display},
16        hash::Hash,
17        ops::*,
18    },
19};
20
21pub trait CssNumber:
22    Sized
23    + Copy
24    + Clone
25    + PartialEq<Self>
26    + Eq
27    + PartialOrd
28    + Ord
29    + Hash
30    + ToCss
31    + Default
32    + Add<Self, Output = Self>
33    + AddAssign<Self>
34    + Sub<Self, Output = Self>
35    + SubAssign<Self>
36    + Mul<Self, Output = Self>
37    + MulAssign<Self>
38    + Div<Self, Output = Self>
39    + DivAssign<Self>
40    + Rem<Self, Output = Self>
41    + RemAssign<Self>
42    + Neg<Output = Self>
43    + Debug
44    + Display
45    + Deref
46    + From<u16>
47    + From<u8>
48    + CssNumberNewType<Self>
49    + Unit<Number = Self>
50    + AppUnitsPer
51{
52    const Zero: Self;
53
54    const One: Self;
55
56    const Maximum: Self;
57
58    const Minimum: Self;
59
60    const DotsPerInch: Self;
61
62    const CentimetresPerInch: Self;
63
64    #[inline(always)]
65    fn new(value: f32) -> Result<Self, CssNumberConversionError> {
66        const NegativeZero: f32 = -0.0_f32;
67        const PositiveZero: f32 = 0.0_f32;
68
69        if value.is_finite() {
70            if value == NegativeZero {
71                if Self::can_be_negative() {
72                    Ok(Self::_construct(PositiveZero))
73                } else {
74                    Err(NegativeNumberMayNotBeAllowed)
75                }
76            } else {
77                Ok(Self::_construct(value))
78            }
79        } else if !Self::can_be_negative() && value.is_sign_negative() {
80            Err(NegativeNumberMayNotBeAllowed)
81        } else if value.is_infinite() {
82            Err(InfinityIsNotAllowed)
83        } else if value.is_nan() {
84            Err(NotANumberIsNotAllowed)
85        } else {
86            unreachable!("What other kind of f32 is there?");
87        }
88    }
89
90    fn as_f32(&self) -> f32;
91
92    fn as_u32(&self) -> u32;
93
94    #[inline(always)]
95    fn round(self) -> Self {
96        Self::_construct(self.to_f32().round())
97    }
98
99    #[inline(always)]
100    fn abs(self) -> Self {
101        Self::_construct(self.to_f32().abs())
102    }
103
104    #[inline(always)]
105    fn clamp(value: f32) -> Self {
106        if value.is_infinite() {
107            if value.is_sign_positive() {
108                Self::Maximum
109            } else {
110                Self::Minimum
111            }
112        } else if value.is_sign_negative() && !Self::can_be_negative() {
113            Self::Zero
114        } else {
115            Self::_construct(value)
116        }
117    }
118
119    #[inline(always)]
120    fn can_be_negative() -> bool {
121        Self::Minimum.is_negative()
122    }
123
124    #[doc(hidden)]
125    fn _construct(value: f32) -> Self;
126
127    fn parseNumber<'i>(
128        value: f32,
129        _int_value: Option<i32>,
130    ) -> Result<Self, ParseError<'i, CustomParseError<'i>>>;
131}