use super::ConfigFileError;
use hurl_core::reader::Reader;
pub fn skip_whitespace_and_comments(reader: &mut Reader) {
loop {
reader.read_while(|c: char| c.is_whitespace());
if reader.is_eof() {
break;
}
if reader.peek() == Some('#') {
reader.read_while(|c: char| c != '\n');
if reader.peek() == Some('\n') {
reader.read(); }
} else {
break;
}
}
}
pub fn expect_no_value(reader: &mut Reader) -> Result<(), ConfigFileError> {
loop {
reader.read_while(|c: char| c == ' ' || c == '\t');
if reader.is_eof() {
break;
}
if reader.peek() == Some('#') {
reader.read_while(|c: char| c != '\n');
if reader.peek() == Some('\n') {
reader.read(); }
} else if reader.peek() == Some('\n') {
reader.read(); break;
} else {
return Err(ConfigFileError::new(
reader.cursor().pos,
"Not expecting a value for this option",
));
}
}
Ok(())
}
pub fn parse_value(reader: &mut Reader) -> Result<String, ConfigFileError> {
if let Some('"') = reader.peek() {
reader.read(); let value = reader.read_while(|c| c != '"');
if reader.peek() == Some('"') {
reader.read(); Ok(value.trim().to_string())
} else {
Err(ConfigFileError::new(
reader.cursor().pos,
"Missing closing quote",
))
}
} else {
let s = reader.read_while(|c| c != '\n').trim().to_string();
Ok(s)
}
}
pub fn parse_value_separator(reader: &mut Reader) -> Result<(), ConfigFileError> {
let s = spaces(reader);
if s.is_empty() {
if reader.peek() == Some('=') {
reader.read();
Ok(())
} else {
Err(ConfigFileError::new(
reader.cursor().pos,
"Expecting a value using space or '=' separator",
))
}
} else {
Ok(())
}
}
fn spaces(reader: &mut Reader) -> String {
reader.read_while(|c: char| c == ' ' || c == '\t')
}
#[cfg(test)]
mod tests {
use hurl_core::reader::{CharPos, Pos};
use super::*;
#[test]
fn test_parse_value_separator() {
let mut reader = Reader::new(" x");
parse_value_separator(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(1, 3));
let mut reader = Reader::new("= x");
parse_value_separator(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(1, 2));
}
#[test]
fn test_parse_value_separator_error() {
let mut reader = Reader::new("x");
assert_eq!(
parse_value_separator(&mut reader).unwrap_err(),
ConfigFileError::new(
Pos::new(1, 1),
"Expecting a value using space or '=' separator"
)
);
}
#[test]
fn test_skip_whitespace_and_comments() {
let mut reader =
Reader::new("# This is a comment\n # Another comment\n option=value\n");
skip_whitespace_and_comments(&mut reader);
assert_eq!((reader.cursor().pos), Pos::new(3, 4));
}
#[test]
fn test_expect_end_of_line() {
let mut reader = Reader::new("\n");
expect_no_value(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(2, 1));
let mut reader = Reader::new(" \n");
expect_no_value(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(2, 1));
let mut reader = Reader::new(" ");
expect_no_value(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(1, 3));
let mut reader = Reader::new(" # Comment\n");
expect_no_value(&mut reader).unwrap();
assert_eq!((reader.cursor().pos), Pos::new(2, 1));
}
#[test]
fn test_expect_end_of_line_error() {
let mut reader = Reader::new("x\n");
assert_eq!(
expect_no_value(&mut reader).unwrap_err(),
ConfigFileError::new(Pos::new(1, 1), "Not expecting a value for this option")
);
}
#[test]
fn test_parse_value() {
let mut reader = Reader::new("\n");
assert_eq!(parse_value(&mut reader).unwrap(), "");
assert_eq!((reader.cursor().index), CharPos(0));
let mut reader = Reader::new("1\n");
assert_eq!(parse_value(&mut reader).unwrap(), "1");
assert_eq!((reader.cursor().index), CharPos(1));
let mut reader = Reader::new("\"Hello\"\n");
assert_eq!(parse_value(&mut reader).unwrap(), "Hello");
assert_eq!((reader.cursor().index), CharPos(7));
let mut reader = Reader::new("\"Hello\nBob!\"\n");
assert_eq!(parse_value(&mut reader).unwrap(), "Hello\nBob!");
assert_eq!((reader.cursor().index), CharPos(12));
}
#[test]
fn test_inline_value_error() {
let mut reader = Reader::new("\"1\n");
assert_eq!(
parse_value(&mut reader).unwrap_err(),
ConfigFileError::new(Pos::new(2, 1), "Missing closing quote")
);
assert_eq!((reader.cursor().index), CharPos(3));
}
}