bookdata/parsing/
mod.rs

1//! Parsing utilities.  Format-specific parsing is in various other modules.
2use std::error::Error as StdError;
3use std::str::FromStr;
4
5use anyhow::{anyhow, Result};
6
7pub mod bindata;
8pub mod dates;
9#[cfg(test)]
10mod test_dates;
11
12pub use bindata::decode_hex_i64_pair;
13
14/// Trim a string, and convert to None if it is empty.
15pub fn trim_opt<'a>(s: &'a str) -> Option<&'a str> {
16    let s2 = s.trim();
17    if s2.is_empty() {
18        None
19    } else {
20        Some(s2)
21    }
22}
23
24/// Trim a string, and convert to None if it is empty.
25pub fn trim_owned(s: &str) -> Option<String> {
26    return trim_opt(s).map(|s| s.to_owned());
27}
28
29/// Parse a possibly-empty string into an option.
30pub fn parse_opt<T: FromStr>(s: &str) -> Result<Option<T>>
31where
32    T::Err: StdError + Sync + Send + 'static,
33{
34    let so = trim_opt(s);
35    // we can't just use map because we need to propagate errors
36    Ok(match so {
37        None => None,
38        Some(s) => Some(match s.parse() {
39            Ok(v) => v,
40            Err(e) => return Err(anyhow!("error parsing ‘{}’: {}", s, e)),
41        }),
42    })
43}