Hi All,
I'm (obviously) very new to Rust. I'm trying to parse a string value containing a list of ranges. These are inclusive and can be open or closed. Example "1-3,5 "
should result in [1..=3, 5..=5]
. I was able to do a hacky version that just panicked whenever it ran into a problem. Now I'm trying to evolve that to use Result
. The problem is that I'm getting compiler errors wherever I'm using the ?
. Example:
the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
I can't figure out why since parse_positions()
does return a Result
. Can anyone help?
code:
use core::fmt;
use std::ops::RangeInclusive;
#[derive(Debug)]
struct PositionParseError {
message: String,
}
impl fmt::Display for PositionParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.message)
}
}
type PositionList = Vec<RangeInclusive<u32>>;
fn parse_range_u32(s: &str) -> Result<u32, PositionParseError> {
s.parse().or(Err(PositionParseError{message: format!("Couldn't parse `{}` as range position", s)}))
}
fn parse_positions(s: &str) -> Result<PositionList, PositionParseError> {
let result: PositionList = s
.split(|c| c == ',' || c == ' ')
.map(|range_spec| {
let range_parts: Vec<&str> = range_spec.split("-").collect();
match range_parts.as_slice() {
["", end] => {
let end = parse_range_u32(end)?;
1..=end
},
[start, ""] => {
let start = parse_range_u32(start)?;
start..=std::u32::MAX
},
[start, end] => {
let start = parse_range_u32(start)?;
let end = parse_range_u32(end)?;
start..=end
},
[start] => {
let start = parse_range_u32(start)?;
start..=start
},
_ => return Err(PositionParseError{message:format!("Couldn't parse `{}` as range", range_spec)})
}
})
.collect();
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_single_position() {
assert_eq!(parse_positions("1").unwrap(), vec![1u32..=1u32]);
}
#[test]
fn test_parse_comma_separated_positions() {
assert_eq!(
parse_positions("1,2").unwrap(),
vec![1u32..=1u32, 2u32..=2u32]
);
}
#[test]
fn test_parse_space_separated_positions() {
assert_eq!(
parse_positions("1 2").unwrap(),
vec![1u32..=1u32, 2u32..=2u32]
);
}
#[test]
fn test_parse_range_positions() {
assert_eq!(parse_positions("1-2").unwrap(), vec![1u32..=2u32]);
}
#[test]
fn test_parse_open_left_range_positions() {
assert_eq!(parse_positions("-3").unwrap(), vec![1u32..=3u32]);
}
#[test]
fn test_parse_open_right_range_positions() {
assert_eq!(parse_positions("7-").unwrap(), vec![7u32..=std::u32::MAX]);
}
}