File: replace-floating-point-with-integer.patch

package info (click to toggle)
rust-iso8601 0.4.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 248 kB
  • sloc: makefile: 6
file content (127 lines) | stat: -rw-r--r-- 4,484 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
The commit information below represents what I submitted to upstream
in a pull request at debian/patches/replace-floating-point-with-integer.patch
the actual patch in this file differs slightly because of adaptations needed
to suit the version of the pacakge in Debian.

commit f5ed7667eb7639a480390d728153782119244bb1
Author: Peter Michael Green <plugwash@debian.org>
Date:   Sat Aug 21 20:53:05 2021 +0000

    Replace rounding-error prone floating point code with robust integer code.

Index: iso8601/src/parsers.rs
===================================================================
--- iso8601.orig/src/parsers.rs
+++ iso8601/src/parsers.rs
@@ -101,14 +101,6 @@ fn sign(i: &[u8]) -> IResult<&[u8], i32>
     })(i)
 }
 
-fn fractions(i: &[u8]) -> IResult<&[u8], f32> {
-    let (i, digits) = take_while(is_digit)(i)?;
-    let digits = str::from_utf8(digits).unwrap(); // This can't panic, `digits` will only include digits.
-    let f = format!("0.{}", digits).parse().unwrap(); // This can't panic, the string is a valid `f32`.
-
-    Ok((i, f))
-}
-
 // DATE
 
 // [+/-]YYYY
@@ -204,8 +196,25 @@ fn time_second(i: &[u8]) -> IResult<&[u8
     n_digit_in_range(i, 2, 0..=60)
 }
 
-fn time_millisecond(fraction: f32) -> u32 {
-    (1000.0 * fraction) as u32
+fn time_millisecond(i: &[u8]) -> IResult<&[u8], u32> {
+    let (i, mut digits) = take_while(is_digit)(i)?;
+    let mut l = digits.len();
+    if l > 3 {
+        digits = digits.get(0..3).unwrap();
+    }
+    let mut result = 0;
+    if l > 0 {
+        let digits = str::from_utf8(digits).unwrap(); // This can't panic, `digits` will only include digits.
+        result = digits.parse().unwrap();
+    }
+    while l < 3 {
+        result = result * 10;
+        l += 1;
+    }
+    //let fraction: f32 = format!("0.{}", digits).parse().unwrap(); // This can't panic, the string is a valid `f32`.
+
+    //let result = (1000.0 * fraction) as u32;
+    Ok ((i,result))
 }
 
 // HH:MM:[SS][.(m*)][(Z|+...|-...)]
@@ -216,7 +225,7 @@ pub fn parse_time(i: &[u8]) -> IResult<&
             opt(tag(b":")),                                                // :
             time_minute,                                                   // MM
             opt(preceded(opt(tag(b":")), time_second)),                    // [SS]
-            opt(map(preceded(one_of(",."), fractions), time_millisecond)), // [.(m*)]
+            opt(preceded(one_of(",."), time_millisecond)),                 // [.(m*)]
             opt(alt((timezone_hour, timezone_utc))),                       // [(Z|+...|-...)]
         )),
         |(h, _, m, s, ms, z)| {
@@ -288,13 +297,30 @@ fn duration_minute(i: &[u8]) -> IResult<
 // S[S][[,.][MS]]
 fn duration_second_and_millisecond(i: &[u8]) -> IResult<&[u8], (u32, u32)> {
     let (i, s) = m_to_n_digit_in_range(i, 1, 2, 0..=60)?;
-    let (i, ms) = opt(map(preceded(one_of(",."), fractions), duration_millisecond))(i)?;
+    let (i, ms) = opt(preceded(one_of(",."), duration_millisecond))(i)?;
 
     Ok((i, (s, ms.unwrap_or(0))))
 }
 
-fn duration_millisecond(fraction: f32) -> u32 {
-    (1000.0 * fraction) as u32
+fn duration_millisecond(i: &[u8]) -> IResult<&[u8], u32> {
+    let (i, mut digits) = take_while(is_digit)(i)?;
+    let mut l = digits.len();
+    if l > 3 {
+        digits = digits.get(0..3).unwrap();
+    }
+    let mut result = 0;
+    if l > 0 {
+        let digits = str::from_utf8(digits).unwrap(); // This can't panic, `digits` will only include digits.
+        result = digits.parse().unwrap();
+    }
+    while l < 3 {
+        result = result * 10;
+        l += 1;
+    }
+    //let fraction: f32 = format!("0.{}", digits).parse().unwrap(); // This can't panic, the string is a valid `f32`.
+
+    //let result = (1000.0 * fraction) as u32;
+    Ok ((i,result))
 }
 
 fn duration_time(i: &[u8]) -> IResult<&[u8], (u32, u32, u32, u32)> {
Index: iso8601/tests/lib.rs
===================================================================
--- iso8601.orig/tests/lib.rs
+++ iso8601/tests/lib.rs
@@ -22,6 +22,21 @@ fn test_date() {
 
 #[test]
 fn test_millisecond() {
+    let mut i=0;
+    while i < 1000 {
+      assert_eq!(
+        Ok(Time {
+            hour: 16,
+            minute: 43,
+            second: 0,
+            millisecond: i,
+            tz_offset_hours: 0,
+            tz_offset_minutes: 0
+        }),
+        time(format!("16:43:00.{:0>3}",i).as_str())
+      );
+      i+=1;
+    }
     assert_eq!(
         Ok(Time {
             hour: 16,