@@ -36,14 +36,77 @@ pub(crate) struct MatchVisitor<'a> {
3636 inner : & ' a SpanMatch ,
3737}
3838
39- #[ derive( Debug , Clone , PartialOrd , Ord , Eq , PartialEq ) ]
39+ #[ derive( Debug , Clone ) ]
4040pub ( crate ) enum ValueMatch {
4141 Bool ( bool ) ,
42+ F64 ( f64 ) ,
4243 U64 ( u64 ) ,
4344 I64 ( i64 ) ,
45+ NaN ,
4446 Pat ( Box < MatchPattern > ) ,
4547}
4648
49+ impl Eq for ValueMatch { }
50+
51+ impl PartialEq for ValueMatch {
52+ fn eq ( & self , other : & Self ) -> bool {
53+ use ValueMatch :: * ;
54+ match ( self , other) {
55+ ( Bool ( a) , Bool ( b) ) => a. eq ( b) ,
56+ ( F64 ( a) , F64 ( b) ) => {
57+ debug_assert ! ( !a. is_nan( ) ) ;
58+ debug_assert ! ( !b. is_nan( ) ) ;
59+
60+ a. eq ( b)
61+ }
62+ ( U64 ( a) , U64 ( b) ) => a. eq ( b) ,
63+ ( I64 ( a) , I64 ( b) ) => a. eq ( b) ,
64+ ( NaN , NaN ) => true ,
65+ ( Pat ( a) , Pat ( b) ) => a. eq ( b) ,
66+ _ => false ,
67+ }
68+ }
69+ }
70+
71+ impl Ord for ValueMatch {
72+ fn cmp ( & self , other : & Self ) -> Ordering {
73+ use ValueMatch :: * ;
74+ match ( self , other) {
75+ ( Bool ( this) , Bool ( that) ) => this. cmp ( that) ,
76+ ( Bool ( _) , _) => Ordering :: Less ,
77+
78+ ( F64 ( this) , F64 ( that) ) => this
79+ . partial_cmp ( that)
80+ . expect ( "`ValueMatch::F64` may not contain `NaN` values" ) ,
81+ ( F64 ( _) , Bool ( _) ) => Ordering :: Greater ,
82+ ( F64 ( _) , _) => Ordering :: Less ,
83+
84+ ( NaN , NaN ) => Ordering :: Equal ,
85+ ( NaN , Bool ( _) ) | ( NaN , F64 ( _) ) => Ordering :: Greater ,
86+ ( NaN , _) => Ordering :: Less ,
87+
88+ ( U64 ( this) , U64 ( that) ) => this. cmp ( that) ,
89+ ( U64 ( _) , Bool ( _) ) | ( U64 ( _) , F64 ( _) ) | ( U64 ( _) , NaN ) => Ordering :: Greater ,
90+ ( U64 ( _) , _) => Ordering :: Less ,
91+
92+ ( I64 ( this) , I64 ( that) ) => this. cmp ( that) ,
93+ ( I64 ( _) , Bool ( _) ) | ( I64 ( _) , F64 ( _) ) | ( I64 ( _) , NaN ) | ( I64 ( _) , U64 ( _) ) => {
94+ Ordering :: Greater
95+ }
96+ ( I64 ( _) , _) => Ordering :: Less ,
97+
98+ ( Pat ( this) , Pat ( that) ) => this. cmp ( that) ,
99+ ( Pat ( _) , _) => Ordering :: Greater ,
100+ }
101+ }
102+ }
103+
104+ impl PartialOrd for ValueMatch {
105+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
106+ Some ( self . cmp ( other) )
107+ }
108+ }
109+
47110#[ derive( Debug , Clone ) ]
48111pub ( crate ) struct MatchPattern {
49112 pub ( crate ) matcher : Pattern ,
@@ -127,13 +190,22 @@ impl PartialOrd for Match {
127190
128191// === impl ValueMatch ===
129192
193+ fn value_match_f64 ( v : f64 ) -> ValueMatch {
194+ if v. is_nan ( ) {
195+ ValueMatch :: NaN
196+ } else {
197+ ValueMatch :: F64 ( v)
198+ }
199+ }
200+
130201impl FromStr for ValueMatch {
131202 type Err = matchers:: Error ;
132203 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
133204 s. parse :: < bool > ( )
134205 . map ( ValueMatch :: Bool )
135206 . or_else ( |_| s. parse :: < u64 > ( ) . map ( ValueMatch :: U64 ) )
136207 . or_else ( |_| s. parse :: < i64 > ( ) . map ( ValueMatch :: I64 ) )
208+ . or_else ( |_| s. parse :: < f64 > ( ) . map ( value_match_f64) )
137209 . or_else ( |_| {
138210 s. parse :: < MatchPattern > ( )
139211 . map ( |p| ValueMatch :: Pat ( Box :: new ( p) ) )
@@ -145,6 +217,8 @@ impl fmt::Display for ValueMatch {
145217 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
146218 match self {
147219 ValueMatch :: Bool ( ref inner) => fmt:: Display :: fmt ( inner, f) ,
220+ ValueMatch :: F64 ( ref inner) => fmt:: Display :: fmt ( inner, f) ,
221+ ValueMatch :: NaN => fmt:: Display :: fmt ( & f64:: NAN , f) ,
148222 ValueMatch :: I64 ( ref inner) => fmt:: Display :: fmt ( inner, f) ,
149223 ValueMatch :: U64 ( ref inner) => fmt:: Display :: fmt ( inner, f) ,
150224 ValueMatch :: Pat ( ref inner) => fmt:: Display :: fmt ( inner, f) ,
@@ -275,6 +349,18 @@ impl SpanMatch {
275349}
276350
277351impl < ' a > Visit for MatchVisitor < ' a > {
352+ fn record_f64 ( & mut self , field : & Field , value : f64 ) {
353+ match self . inner . fields . get ( field) {
354+ Some ( ( ValueMatch :: NaN , ref matched) ) if value. is_nan ( ) => {
355+ matched. store ( true , Release ) ;
356+ }
357+ Some ( ( ValueMatch :: F64 ( ref e) , ref matched) ) if ( value - * e) . abs ( ) < f64:: EPSILON => {
358+ matched. store ( true , Release ) ;
359+ }
360+ _ => { }
361+ }
362+ }
363+
278364 fn record_i64 ( & mut self , field : & Field , value : i64 ) {
279365 use std:: convert:: TryInto ;
280366
0 commit comments