use crate::BsdlError;
pub fn strip_prefix<'a>(s: &'a str, c: char) -> Result<&'a str, BsdlError> {
let s = s.trim_start();
let s = s
.strip_prefix(c)
.ok_or_else(|| BsdlError::MissingCharError(format!("expected {}", c)))?;
let s = s.trim_start();
Ok(s)
}
pub fn strip_parenthesis<'a>(s: &'a str) -> Result<&'a str, BsdlError> {
let s = s.trim();
let s = s.strip_prefix('(').ok_or(BsdlError::ParenthesisError)?;
let s = s.strip_suffix(')').ok_or(BsdlError::ParenthesisError)?;
let s = s.trim();
Ok(s)
}
pub fn split_parenthesis<'a>(s: &'a str) -> Result<(&'a str, &'a str), BsdlError> {
let s = s.trim_start();
if !s.starts_with('(') {
return Err(BsdlError::ParenthesisError);
}
let mut open_paren = 1;
let s = &s[1..];
for (i, c) in s.chars().enumerate() {
if c == ')' {
open_paren -= 1;
if open_paren == 0 {
return Ok((&s[..i], &s[i + 1..]));
}
}
if c == '(' {
open_paren += 1;
}
}
let close = s.find(')').ok_or(BsdlError::ParenthesisError)?;
Ok((&s[1..close], &s[close + 1..]))
}
#[cfg(test)]
mod test_split_parenthesis {
use super::*;
#[test]
fn test_split_parenthesis() {
let (a, b) = split_parenthesis(" (a,(b)) c,d () ").unwrap();
println!("{a}, {b}");
assert!(a == "a,(b)");
assert!(b == " c,d () ");
let (a, b) = split_parenthesis(" (a,b)").unwrap();
assert!(a == "a,b");
assert!(b == "");
split_parenthesis(" no )").expect_err("missing open paren");
}
}
pub fn strip_quotes<'a>(s: &'a str) -> Result<&'a str, BsdlError> {
let s = s.trim();
let s = s.strip_prefix('"').ok_or(BsdlError::QuotesMissingError)?;
let s = s.strip_suffix('"').ok_or(BsdlError::QuotesMissingError)?;
let s = s.trim();
Ok(s)
}
pub fn strip_whitespace_comments(buf: &str) -> &str {
let mut buf = buf;
let mut c_prev = ' ';
let mut in_quote = false;
let mut comment = buf.len();
for (i, c) in buf.chars().enumerate() {
if in_quote {
in_quote = c != '"';
continue;
}
if (c == '-') & (c_prev == '-') {
comment = i - 1;
break;
}
if c == '"' {
in_quote = true;
}
c_prev = c;
}
buf = &buf[0..comment];
buf.trim()
}
pub fn find_first_comma_outside_paren(buf: &str) -> Result<Option<usize>, BsdlError> {
let mut open_paren = 0;
for (i, c) in buf.chars().enumerate() {
if (open_paren == 0) & (c == ',') {
return Ok(Some(i));
}
if c == '(' {
open_paren += 1;
}
if c == ')' {
if open_paren == 0 {
return Err(BsdlError::ParenthesisError);
}
open_paren -= 1;
}
}
Ok(None)
}
pub fn split_once_at_first_comma_outside_paren(buf: &str) -> Result<(&str, &str), BsdlError> {
let comma = find_first_comma_outside_paren(buf)?;
match comma {
None => Ok((buf, "")),
Some(comma) => Ok((&buf[0..comma], &buf[comma + 1..])),
}
}
#[cfg(test)]
mod test_find_first_comma_outside_paren {
use super::*;
#[test]
fn test_find_first_comma_outside_paren() {
let x = find_first_comma_outside_paren("(,),");
println!("{x:?}");
assert!(x.unwrap().unwrap() == 3);
let x = find_first_comma_outside_paren("(,)");
println!("{x:?}");
assert!(x.unwrap() == None);
let x = find_first_comma_outside_paren(" ),");
println!("{x:?}");
assert!(x.is_err());
}
}