a1/row/
from_str.rs

1use crate::{Error, Index, Row};
2use std::str::FromStr;
3
4/// Parses *just* the "1" part of an "A1" reference.  Which would be a number, possibly prefixed
5/// with `$`.  Any other input that is supplied will throw an error.
6impl FromStr for Row {
7    type Err = Error;
8
9    fn from_str(s: &str) -> Result<Self, Self::Err> {
10        let mut absolute = false;
11
12        let ys = if let Some(without_abs) = s.strip_prefix('$') {
13            absolute = true;
14            without_abs
15        } else {
16            s
17        };
18
19        let y = ys.parse::<Index>().map_err(|e| {
20            Error::parse_error(
21                s,
22                format!("Error parsing number part of A1 reference: {e:?}"),
23            )
24        })?;
25
26        if y < 1 {
27            return Err(Error::parse_error(
28                y.to_string(),
29                "A1 reference must be greater than 0",
30            ));
31        }
32
33        Ok(Self { absolute, y: y - 1 })
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use crate::*;
40
41    #[test]
42    fn from_str_ok() {
43        assert_eq!(Row::from_str("1").unwrap(), Row::new(0));
44        assert_eq!(Row::from_str("124").unwrap(), Row::new(123));
45    }
46
47    #[test]
48    fn from_str_ok_absolute() {
49        assert_eq!(
50            Row::from_str("$1").unwrap(),
51            Row {
52                y: 0,
53                absolute: true
54            }
55        );
56        assert_eq!(
57            Row::from_str("$124").unwrap(),
58            Row {
59                y: 123,
60                absolute: true
61            }
62        );
63    }
64
65    #[test]
66    fn from_str_error() {
67        assert!(Row::from_str("ABC").is_err());
68        assert!(Row::from_str(" ! < ").is_err());
69    }
70}