@@ -8,6 +8,7 @@ use crate::traits::private::AddInternal;
88use crate :: traits:: { Parse , ToCss } ;
99use cssparser:: * ;
1010
11+ use super :: angle:: Angle ;
1112use super :: number:: CSSNumber ;
1213
1314/// A CSS [math function](https://www.w3.org/TR/css-values-4/#math-function).
@@ -203,6 +204,36 @@ pub enum Calc<V> {
203204 Function ( Box < MathFunction < V > > ) ,
204205}
205206
207+ enum_property ! {
208+ /// A mathematical constant.
209+ pub enum Constant {
210+ /// The base of the natural logarithm
211+ "e" : E ,
212+ /// The ratio of a circle’s circumference to its diameter
213+ "pi" : Pi ,
214+ /// infinity
215+ "infinity" : Infinity ,
216+ /// -infinity
217+ "-infinity" : NegativeInfinity ,
218+ /// Not a number.
219+ "nan" : Nan ,
220+ }
221+ }
222+
223+ impl Into < f32 > for Constant {
224+ fn into ( self ) -> f32 {
225+ use std:: f32:: consts;
226+ use Constant :: * ;
227+ match self {
228+ E => consts:: E ,
229+ Pi => consts:: PI ,
230+ Infinity => f32:: INFINITY ,
231+ NegativeInfinity => -f32:: INFINITY ,
232+ Nan => f32:: NAN ,
233+ }
234+ }
235+ }
236+
206237impl <
207238 ' i ,
208239 V : Parse < ' i >
@@ -211,8 +242,9 @@ impl<
211242 + TryRound
212243 + TryRem
213244 + std:: cmp:: PartialOrd < V >
214- + std:: convert:: Into < Calc < V > >
215- + std:: convert:: From < Calc < V > >
245+ + Into < Calc < V > >
246+ + From < Calc < V > >
247+ + TryFrom < Angle >
216248 + Clone
217249 + std:: fmt:: Debug ,
218250 > Parse < ' i > for Calc < V >
@@ -353,7 +385,13 @@ impl<
353385 Ok ( Calc :: Function ( Box :: new( MathFunction :: Rem ( a, b) ) ) )
354386 } )
355387 } ,
356- _ => Err ( location. new_unexpected_token_error( Token :: Ident ( f. clone( ) ) ) ) ,
388+ "sin" => Self :: parse_trig( input, f32 :: sin, false ) ,
389+ "cos" => Self :: parse_trig( input, f32 :: cos, false ) ,
390+ "tan" => Self :: parse_trig( input, f32 :: tan, false ) ,
391+ "asin" => Self :: parse_trig( input, f32 :: asin, true ) ,
392+ "acos" => Self :: parse_trig( input, f32 :: acos, true ) ,
393+ "atan" => Self :: parse_trig( input, f32 :: atan, true ) ,
394+ _ => Err ( location. new_unexpected_token_error( Token :: Ident ( f. clone( ) ) ) ) ,
357395 }
358396 }
359397}
@@ -366,8 +404,9 @@ impl<
366404 + TryRound
367405 + TryRem
368406 + std:: cmp:: PartialOrd < V >
369- + std:: convert:: Into < Calc < V > >
370- + std:: convert:: From < Calc < V > >
407+ + Into < Calc < V > >
408+ + From < Calc < V > >
409+ + TryFrom < Angle >
371410 + Clone
372411 + std:: fmt:: Debug ,
373412 > Calc < V >
@@ -464,6 +503,10 @@ impl<
464503 return Ok ( Calc :: Number ( num) ) ;
465504 }
466505
506+ if let Ok ( constant) = input. try_parse ( Constant :: parse) {
507+ return Ok ( Calc :: Number ( constant. into ( ) ) ) ;
508+ }
509+
467510 if let Ok ( value) = input. try_parse ( V :: parse) {
468511 return Ok ( Calc :: Value ( Box :: new ( value) ) ) ;
469512 }
@@ -507,6 +550,31 @@ impl<
507550 }
508551 reduced
509552 }
553+
554+ fn parse_trig < ' t , F : FnOnce ( f32 ) -> f32 > (
555+ input : & mut Parser < ' i , ' t > ,
556+ f : F ,
557+ to_angle : bool ,
558+ ) -> Result < Self , ParseError < ' i , ParserError < ' i > > > {
559+ input. parse_nested_block ( |input| {
560+ let v: Calc < Angle > = Calc :: parse_sum ( input) ?;
561+ let rad = match v {
562+ Calc :: Value ( angle) if !to_angle => f ( angle. to_radians ( ) ) ,
563+ Calc :: Number ( v) => f ( v) ,
564+ _ => return Err ( input. new_custom_error ( ParserError :: InvalidValue ) ) ,
565+ } ;
566+
567+ if to_angle && !rad. is_nan ( ) {
568+ if let Ok ( v) = V :: try_from ( Angle :: Rad ( rad) ) {
569+ return Ok ( Calc :: Value ( Box :: new ( v) ) ) ;
570+ } else {
571+ return Err ( input. new_custom_error ( ParserError :: InvalidValue ) ) ;
572+ }
573+ } else {
574+ Ok ( Calc :: Number ( rad) )
575+ }
576+ } )
577+ }
510578}
511579
512580impl < V : std:: ops:: Mul < f32 , Output = V > > std:: ops:: Mul < f32 > for Calc < V > {
0 commit comments