simple_test/util/
number.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/// parse str radix from golang format, but: if 8 or 9 is included
16/// in octal literal, it will be treated as decimal literal.
17/// This function panics if str is not dec, oct, hex format
18pub fn parse_str_radix(s: &str) -> Result<f64, String> {
19    let st: String = s
20        .chars()
21        .map(|c| c.to_ascii_lowercase())
22        .filter(|c| !c.is_whitespace())
23        .collect();
24
25    let mut is_not_decimal = false;
26    if st.contains('x') {
27        is_not_decimal = true;
28    }
29
30    if !is_not_decimal
31        && (st.starts_with("-0") || st.starts_with("+0") || st.starts_with('0'))
32        && !st.contains('.')
33        && !st.contains('8')
34        && !st.contains('9')
35        && !st.eq("0")
36        && !st.eq("+0")
37        && !st.eq("-0")
38    {
39        is_not_decimal = true;
40    }
41
42    if is_not_decimal {
43        let i = if st.starts_with("-0x") {
44            i64::from_str_radix(st.strip_prefix("-0x").unwrap(), 16).map(|x| -x)
45        } else if st.starts_with("+0x") {
46            i64::from_str_radix(st.strip_prefix("+0x").unwrap(), 16)
47        } else if st.starts_with("0x") {
48            i64::from_str_radix(st.strip_prefix("0x").unwrap(), 16)
49        } else if st.starts_with("-0") {
50            i64::from_str_radix(st.strip_prefix("-0").unwrap(), 8).map(|x| -x)
51        } else if st.starts_with("+0") {
52            i64::from_str_radix(st.strip_prefix("+0").unwrap(), 8)
53        } else {
54            i64::from_str_radix(st.strip_prefix('0').unwrap(), 8) // starts with '0'
55        };
56        return i
57            .map(|x| x as f64)
58            .map_err(|_| format!("ParseFloatError. {s} can't be parsed into i64"));
59    }
60    st.parse()
61        .map_err(|_| format!("ParseFloatError. {s} can't be parsed into f64"))
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_parse_str_radix() {
70        assert_eq!(parse_str_radix("0x2f").unwrap(), 47_f64);
71        assert_eq!(parse_str_radix("+0x2f").unwrap(), 47_f64);
72        assert_eq!(parse_str_radix("- 0x2f ").unwrap(), -47_f64);
73        assert_eq!(parse_str_radix("017").unwrap(), 15_f64);
74        assert_eq!(parse_str_radix("-017").unwrap(), -15_f64);
75        assert_eq!(parse_str_radix("+017").unwrap(), 15_f64);
76        assert_eq!(parse_str_radix("2023.0128").unwrap(), 2023.0128_f64);
77        assert_eq!(parse_str_radix("-4.14").unwrap(), -4.14_f64);
78        assert_eq!(parse_str_radix("+3.718").unwrap(), 3.718_f64);
79        assert_eq!(parse_str_radix("-0.14").unwrap(), -0.14_f64);
80        assert_eq!(parse_str_radix("+0.718").unwrap(), 0.718_f64);
81        assert_eq!(parse_str_radix("0.718").unwrap(), 0.718_f64);
82        assert_eq!(parse_str_radix("089").unwrap(), 89_f64);
83        assert_eq!(parse_str_radix("+089").unwrap(), 89_f64);
84        assert_eq!(parse_str_radix("-089").unwrap(), -89_f64);
85        assert_eq!(parse_str_radix("+0").unwrap(), 0_f64);
86        assert_eq!(parse_str_radix("-0").unwrap(), 0_f64);
87        assert_eq!(parse_str_radix("0").unwrap(), 0_f64);
88
89        assert!(parse_str_radix("rust").is_err());
90        assert!(parse_str_radix("0xgolang").is_err());
91        assert!(parse_str_radix("0clojure").is_err());
92    }
93}