aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/array.rs2
-rw-r--r--src/parser/datetime.rs40
-rw-r--r--src/parser/error.rs87
-rw-r--r--src/parser/errors.rs316
-rw-r--r--src/parser/inline_table.rs27
-rw-r--r--src/parser/key.rs36
-rw-r--r--src/parser/mod.rs18
-rw-r--r--src/parser/numbers.rs11
-rw-r--r--src/parser/state.rs23
-rw-r--r--src/parser/strings.rs12
-rw-r--r--src/parser/trivia.rs2
-rw-r--r--src/parser/value.rs4
12 files changed, 216 insertions, 362 deletions
diff --git a/src/parser/array.rs b/src/parser/array.rs
index e3b1f3f..0783191 100644
--- a/src/parser/array.rs
+++ b/src/parser/array.rs
@@ -81,6 +81,8 @@ pub(crate) fn array_value<'i>(
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
diff --git a/src/parser/datetime.rs b/src/parser/datetime.rs
index 6e89b97..945dc69 100644
--- a/src/parser/datetime.rs
+++ b/src/parser/datetime.rs
@@ -1,6 +1,6 @@
use std::ops::RangeInclusive;
-use crate::parser::errors::CustomError;
+use crate::parser::error::CustomError;
use crate::parser::prelude::*;
use crate::parser::trivia::from_utf8_unchecked;
@@ -9,6 +9,7 @@ use winnow::combinator::alt;
use winnow::combinator::cut_err;
use winnow::combinator::opt;
use winnow::combinator::preceded;
+use winnow::stream::Stream as _;
use winnow::token::one_of;
use winnow::token::take_while;
use winnow::trace::trace;
@@ -53,12 +54,35 @@ pub(crate) fn date_time(input: &mut Input<'_>) -> PResult<Datetime> {
// full-date = date-fullyear "-" date-month "-" date-mday
pub(crate) fn full_date(input: &mut Input<'_>) -> PResult<Date> {
- trace(
- "full-date",
- (date_fullyear, b'-', cut_err((date_month, b'-', date_mday)))
- .map(|(year, _, (month, _, day))| Date { year, month, day }),
- )
- .parse_next(input)
+ trace("full-date", full_date_).parse_next(input)
+}
+
+fn full_date_(input: &mut Input<'_>) -> PResult<Date> {
+ let year = date_fullyear.parse_next(input)?;
+ let _ = b'-'.parse_next(input)?;
+ let month = cut_err(date_month).parse_next(input)?;
+ let _ = cut_err(b'-').parse_next(input)?;
+ let day_start = input.checkpoint();
+ let day = cut_err(date_mday).parse_next(input)?;
+
+ let is_leap_year = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
+ let max_days_in_month = match month {
+ 2 if is_leap_year => 29,
+ 2 => 28,
+ 4 | 6 | 9 | 11 => 30,
+ _ => 31,
+ };
+ if max_days_in_month < day {
+ input.reset(day_start);
+ return Err(winnow::error::ErrMode::from_external_error(
+ input,
+ winnow::error::ErrorKind::Verify,
+ CustomError::OutOfRange,
+ )
+ .cut());
+ }
+
+ Ok(Date { year, month, day })
}
// partial-time = time-hour ":" time-minute ":" time-second [time-secfrac]
@@ -239,6 +263,8 @@ pub(crate) fn unsigned_digits<'i, const MIN: usize, const MAX: usize>(
const DIGIT: RangeInclusive<u8> = b'0'..=b'9';
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
diff --git a/src/parser/error.rs b/src/parser/error.rs
new file mode 100644
index 0000000..22e8e66
--- /dev/null
+++ b/src/parser/error.rs
@@ -0,0 +1,87 @@
+use std::error::Error as StdError;
+use std::fmt::{Display, Formatter, Result};
+
+use crate::Key;
+
+#[derive(Debug, Clone)]
+pub(crate) enum CustomError {
+ DuplicateKey {
+ key: String,
+ table: Option<Vec<Key>>,
+ },
+ DottedKeyExtendWrongType {
+ key: Vec<Key>,
+ actual: &'static str,
+ },
+ OutOfRange,
+ #[cfg_attr(feature = "unbounded", allow(dead_code))]
+ RecursionLimitExceeded,
+}
+
+impl CustomError {
+ pub(crate) fn duplicate_key(path: &[Key], i: usize) -> Self {
+ assert!(i < path.len());
+ let key = &path[i];
+ let repr = key
+ .as_repr()
+ .and_then(|key| key.as_raw().as_str())
+ .map(|s| s.to_owned())
+ .unwrap_or_else(|| {
+ #[cfg(feature = "display")]
+ {
+ key.default_repr().as_raw().as_str().unwrap().to_owned()
+ }
+ #[cfg(not(feature = "display"))]
+ {
+ format!("{:?}", key.get())
+ }
+ });
+ Self::DuplicateKey {
+ key: repr,
+ table: Some(path[..i].to_vec()),
+ }
+ }
+
+ pub(crate) fn extend_wrong_type(path: &[Key], i: usize, actual: &'static str) -> Self {
+ assert!(i < path.len());
+ Self::DottedKeyExtendWrongType {
+ key: path[..=i].to_vec(),
+ actual,
+ }
+ }
+}
+
+impl StdError for CustomError {
+ fn description(&self) -> &'static str {
+ "TOML parse error"
+ }
+}
+
+impl Display for CustomError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ match self {
+ CustomError::DuplicateKey { key, table } => {
+ if let Some(table) = table {
+ if table.is_empty() {
+ write!(f, "duplicate key `{}` in document root", key)
+ } else {
+ let path = table.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
+ write!(f, "duplicate key `{}` in table `{}`", key, path)
+ }
+ } else {
+ write!(f, "duplicate key `{}`", key)
+ }
+ }
+ CustomError::DottedKeyExtendWrongType { key, actual } => {
+ let path = key.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
+ write!(
+ f,
+ "dotted key `{}` attempted to extend non-table type ({})",
+ path, actual
+ )
+ }
+ CustomError::OutOfRange => write!(f, "value is out of range"),
+ CustomError::RecursionLimitExceeded => write!(f, "recursion limit exceeded"),
+ }
+ }
+}
diff --git a/src/parser/errors.rs b/src/parser/errors.rs
deleted file mode 100644
index 859ed53..0000000
--- a/src/parser/errors.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-use std::error::Error as StdError;
-use std::fmt::{Display, Formatter, Result};
-
-use crate::parser::prelude::*;
-use crate::Key;
-
-use winnow::error::ContextError;
-use winnow::error::ParseError;
-
-/// Type representing a TOML parse error
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct TomlError {
- message: String,
- original: Option<String>,
- keys: Vec<String>,
- span: Option<std::ops::Range<usize>>,
-}
-
-impl TomlError {
- pub(crate) fn new(error: ParseError<Input<'_>, ContextError>, mut original: Input<'_>) -> Self {
- use winnow::stream::Stream;
-
- let offset = error.offset();
- let span = if offset == original.len() {
- offset..offset
- } else {
- offset..(offset + 1)
- };
-
- let message = error.inner().to_string();
- let original = original.finish();
-
- Self {
- message,
- original: Some(
- String::from_utf8(original.to_owned()).expect("original document was utf8"),
- ),
- keys: Vec::new(),
- span: Some(span),
- }
- }
-
- #[cfg(feature = "serde")]
- pub(crate) fn custom(message: String, span: Option<std::ops::Range<usize>>) -> Self {
- Self {
- message,
- original: None,
- keys: Vec::new(),
- span,
- }
- }
-
- #[cfg(feature = "serde")]
- pub(crate) fn add_key(&mut self, key: String) {
- self.keys.insert(0, key);
- }
-
- /// What went wrong
- pub fn message(&self) -> &str {
- &self.message
- }
-
- /// The start/end index into the original document where the error occurred
- pub fn span(&self) -> Option<std::ops::Range<usize>> {
- self.span.clone()
- }
-
- #[cfg(feature = "serde")]
- pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) {
- self.span = span;
- }
-
- #[cfg(feature = "serde")]
- pub(crate) fn set_original(&mut self, original: Option<String>) {
- self.original = original;
- }
-}
-
-/// Displays a TOML parse error
-///
-/// # Example
-///
-/// TOML parse error at line 1, column 10
-/// |
-/// 1 | 00:32:00.a999999
-/// | ^
-/// Unexpected `a`
-/// Expected `digit`
-/// While parsing a Time
-/// While parsing a Date-Time
-impl Display for TomlError {
- fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- let mut context = false;
- if let (Some(original), Some(span)) = (&self.original, self.span()) {
- context = true;
-
- let (line, column) = translate_position(original.as_bytes(), span.start);
- let line_num = line + 1;
- let col_num = column + 1;
- let gutter = line_num.to_string().len();
- let content = original.split('\n').nth(line).expect("valid line number");
-
- writeln!(
- f,
- "TOML parse error at line {}, column {}",
- line_num, col_num
- )?;
- // |
- for _ in 0..=gutter {
- write!(f, " ")?;
- }
- writeln!(f, "|")?;
-
- // 1 | 00:32:00.a999999
- write!(f, "{} | ", line_num)?;
- writeln!(f, "{}", content)?;
-
- // | ^
- for _ in 0..=gutter {
- write!(f, " ")?;
- }
- write!(f, "|")?;
- for _ in 0..=column {
- write!(f, " ")?;
- }
- // The span will be empty at eof, so we need to make sure we always print at least
- // one `^`
- write!(f, "^")?;
- for _ in (span.start + 1)..(span.end.min(span.start + content.len())) {
- write!(f, "^")?;
- }
- writeln!(f)?;
- }
- writeln!(f, "{}", self.message)?;
- if !context && !self.keys.is_empty() {
- writeln!(f, "in `{}`", self.keys.join("."))?;
- }
-
- Ok(())
- }
-}
-
-impl StdError for TomlError {
- fn description(&self) -> &'static str {
- "TOML parse error"
- }
-}
-
-fn translate_position(input: &[u8], index: usize) -> (usize, usize) {
- if input.is_empty() {
- return (0, index);
- }
-
- let safe_index = index.min(input.len() - 1);
- let column_offset = index - safe_index;
- let index = safe_index;
-
- let nl = input[0..index]
- .iter()
- .rev()
- .enumerate()
- .find(|(_, b)| **b == b'\n')
- .map(|(nl, _)| index - nl - 1);
- let line_start = match nl {
- Some(nl) => nl + 1,
- None => 0,
- };
- let line = input[0..line_start].iter().filter(|b| **b == b'\n').count();
- let line = line;
-
- let column = std::str::from_utf8(&input[line_start..=index])
- .map(|s| s.chars().count() - 1)
- .unwrap_or_else(|_| index - line_start);
- let column = column + column_offset;
-
- (line, column)
-}
-
-#[cfg(test)]
-mod test_translate_position {
- use super::*;
-
- #[test]
- fn empty() {
- let input = b"";
- let index = 0;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, 0));
- }
-
- #[test]
- fn start() {
- let input = b"Hello";
- let index = 0;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, 0));
- }
-
- #[test]
- fn end() {
- let input = b"Hello";
- let index = input.len() - 1;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, input.len() - 1));
- }
-
- #[test]
- fn after() {
- let input = b"Hello";
- let index = input.len();
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, input.len()));
- }
-
- #[test]
- fn first_line() {
- let input = b"Hello\nWorld\n";
- let index = 2;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, 2));
- }
-
- #[test]
- fn end_of_line() {
- let input = b"Hello\nWorld\n";
- let index = 5;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (0, 5));
- }
-
- #[test]
- fn start_of_second_line() {
- let input = b"Hello\nWorld\n";
- let index = 6;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (1, 0));
- }
-
- #[test]
- fn second_line() {
- let input = b"Hello\nWorld\n";
- let index = 8;
- let position = translate_position(&input[..], index);
- assert_eq!(position, (1, 2));
- }
-}
-
-#[derive(Debug, Clone)]
-pub(crate) enum CustomError {
- DuplicateKey {
- key: String,
- table: Option<Vec<Key>>,
- },
- DottedKeyExtendWrongType {
- key: Vec<Key>,
- actual: &'static str,
- },
- OutOfRange,
- #[cfg_attr(feature = "unbounded", allow(dead_code))]
- RecursionLimitExceeded,
-}
-
-impl CustomError {
- pub(crate) fn duplicate_key(path: &[Key], i: usize) -> Self {
- assert!(i < path.len());
- let key = &path[i];
- let repr = key.display_repr();
- Self::DuplicateKey {
- key: repr.into(),
- table: Some(path[..i].to_vec()),
- }
- }
-
- pub(crate) fn extend_wrong_type(path: &[Key], i: usize, actual: &'static str) -> Self {
- assert!(i < path.len());
- Self::DottedKeyExtendWrongType {
- key: path[..=i].to_vec(),
- actual,
- }
- }
-}
-
-impl StdError for CustomError {
- fn description(&self) -> &'static str {
- "TOML parse error"
- }
-}
-
-impl Display for CustomError {
- fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- match self {
- CustomError::DuplicateKey { key, table } => {
- if let Some(table) = table {
- if table.is_empty() {
- write!(f, "duplicate key `{}` in document root", key)
- } else {
- let path = table.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
- write!(f, "duplicate key `{}` in table `{}`", key, path)
- }
- } else {
- write!(f, "duplicate key `{}`", key)
- }
- }
- CustomError::DottedKeyExtendWrongType { key, actual } => {
- let path = key.iter().map(|k| k.get()).collect::<Vec<_>>().join(".");
- write!(
- f,
- "dotted key `{}` attempted to extend non-table type ({})",
- path, actual
- )
- }
- CustomError::OutOfRange => write!(f, "value is out of range"),
- CustomError::RecursionLimitExceeded => write!(f, "recursion limit exceded"),
- }
- }
-}
diff --git a/src/parser/inline_table.rs b/src/parser/inline_table.rs
index 994e003..c2e6619 100644
--- a/src/parser/inline_table.rs
+++ b/src/parser/inline_table.rs
@@ -5,7 +5,7 @@ use winnow::token::one_of;
use winnow::trace::trace;
use crate::key::Key;
-use crate::parser::errors::CustomError;
+use crate::parser::error::CustomError;
use crate::parser::key::key;
use crate::parser::prelude::*;
use crate::parser::trivia::ws;
@@ -44,6 +44,16 @@ fn table_from_pairs(
for (path, kv) in v {
let table = descend_path(&mut root, &path)?;
+
+ // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
+ let mixed_table_types = table.is_dotted() == path.is_empty();
+ if mixed_table_types {
+ return Err(CustomError::DuplicateKey {
+ key: kv.key.get().into(),
+ table: None,
+ });
+ }
+
let key: InternalString = kv.key.get_internal().into();
match table.items.entry(key) {
Entry::Vacant(o) => {
@@ -64,15 +74,26 @@ fn descend_path<'a>(
mut table: &'a mut InlineTable,
path: &'a [Key],
) -> Result<&'a mut InlineTable, CustomError> {
+ let dotted = !path.is_empty();
for (i, key) in path.iter().enumerate() {
let entry = table.entry_format(key).or_insert_with(|| {
let mut new_table = InlineTable::new();
- new_table.set_dotted(true);
+ new_table.set_implicit(dotted);
+ new_table.set_dotted(dotted);
Value::InlineTable(new_table)
});
match *entry {
Value::InlineTable(ref mut sweet_child_of_mine) => {
+ // Since tables cannot be defined more than once, redefining such tables using a
+ // [table] header is not allowed. Likewise, using dotted keys to redefine tables
+ // already defined in [table] form is not allowed.
+ if dotted && !sweet_child_of_mine.is_implicit() {
+ return Err(CustomError::DuplicateKey {
+ key: key.get().into(),
+ table: None,
+ });
+ }
table = sweet_child_of_mine;
}
ref v => {
@@ -144,6 +165,8 @@ fn keyval<'i>(
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
diff --git a/src/parser/key.rs b/src/parser/key.rs
index 12715da..e72b195 100644
--- a/src/parser/key.rs
+++ b/src/parser/key.rs
@@ -7,7 +7,7 @@ use winnow::token::take_while;
use winnow::trace::trace;
use crate::key::Key;
-use crate::parser::errors::CustomError;
+use crate::parser::error::CustomError;
use crate::parser::prelude::*;
use crate::parser::strings::{basic_string, literal_string};
use crate::parser::trivia::{from_utf8_unchecked, ws};
@@ -18,13 +18,13 @@ use crate::RawString;
// key = simple-key / dotted-key
// dotted-key = simple-key 1*( dot-sep simple-key )
pub(crate) fn key(input: &mut Input<'_>) -> PResult<Vec<Key>> {
- trace(
+ let mut key_path = trace(
"dotted-key",
separated1(
(ws.span(), simple_key, ws.span()).map(|(pre, (raw, key), suffix)| {
Key::new(key)
.with_repr_unchecked(Repr::new_unchecked(raw))
- .with_decor(Decor::new(
+ .with_dotted_decor(Decor::new(
RawString::with_span(pre),
RawString::with_span(suffix),
))
@@ -38,7 +38,31 @@ pub(crate) fn key(input: &mut Input<'_>) -> PResult<Vec<Key>> {
Ok::<_, CustomError>(k)
}),
)
- .parse_next(input)
+ .parse_next(input)?;
+
+ let mut leaf_decor = Decor::new("", "");
+ {
+ let first_dotted_decor = key_path
+ .first_mut()
+ .expect("always at least one key")
+ .dotted_decor_mut();
+ if let Some(prefix) = first_dotted_decor.prefix().cloned() {
+ leaf_decor.set_prefix(prefix);
+ first_dotted_decor.set_prefix("");
+ }
+ }
+ let last_key = &mut key_path.last_mut().expect("always at least one key");
+ {
+ let last_dotted_decor = last_key.dotted_decor_mut();
+ if let Some(suffix) = last_dotted_decor.suffix().cloned() {
+ leaf_decor.set_suffix(suffix);
+ last_dotted_decor.set_suffix("");
+ }
+ }
+
+ *last_key.leaf_decor_mut() = leaf_decor;
+
+ Ok(key_path)
}
// simple-key = quoted-key / unquoted-key
@@ -88,6 +112,8 @@ const UNQUOTED_CHAR: (
const DOT_SEP: u8 = b'.';
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
@@ -96,7 +122,7 @@ mod test {
let cases = [
("a", "a"),
(r#""hello\n ""#, "hello\n "),
- (r#"'hello\n '"#, "hello\\n "),
+ (r"'hello\n '", "hello\\n "),
];
for (input, expected) in cases {
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 1b3cc4f..e032202 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -3,7 +3,7 @@
pub(crate) mod array;
pub(crate) mod datetime;
pub(crate) mod document;
-pub(crate) mod errors;
+pub(crate) mod error;
pub(crate) mod inline_table;
pub(crate) mod key;
pub(crate) mod numbers;
@@ -13,7 +13,7 @@ pub(crate) mod table;
pub(crate) mod trivia;
pub(crate) mod value;
-pub use errors::TomlError;
+pub use crate::error::TomlError;
pub(crate) fn parse_document(raw: &str) -> Result<crate::Document, TomlError> {
use prelude::*;
@@ -95,11 +95,11 @@ pub(crate) mod prelude {
#[cfg(not(feature = "unbounded"))]
impl RecursionCheck {
- pub(crate) fn check_depth(depth: usize) -> Result<(), super::errors::CustomError> {
+ pub(crate) fn check_depth(depth: usize) -> Result<(), super::error::CustomError> {
if depth < 128 {
Ok(())
} else {
- Err(super::errors::CustomError::RecursionLimitExceeded)
+ Err(super::error::CustomError::RecursionLimitExceeded)
}
}
@@ -114,7 +114,7 @@ pub(crate) mod prelude {
Err(winnow::error::ErrMode::from_external_error(
input,
winnow::error::ErrorKind::Eof,
- super::errors::CustomError::RecursionLimitExceeded,
+ super::error::CustomError::RecursionLimitExceeded,
))
}
}
@@ -126,7 +126,7 @@ pub(crate) mod prelude {
#[cfg(feature = "unbounded")]
impl RecursionCheck {
- pub(crate) fn check_depth(_depth: usize) -> Result<(), super::errors::CustomError> {
+ pub(crate) fn check_depth(_depth: usize) -> Result<(), super::error::CustomError> {
Ok(())
}
@@ -140,6 +140,8 @@ pub(crate) mod prelude {
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
@@ -182,10 +184,10 @@ hosts = [
"omega"
]
- 'some.wierd .stuff' = """
+ 'some.weird .stuff' = """
like
that
- # """ # this broke my sintax highlighting
+ # """ # this broke my syntax highlighting
" also. like " = '''
that
'''
diff --git a/src/parser/numbers.rs b/src/parser/numbers.rs
index 6e4757f..9681526 100644
--- a/src/parser/numbers.rs
+++ b/src/parser/numbers.rs
@@ -301,7 +301,7 @@ pub(crate) fn inf(input: &mut Input<'_>) -> PResult<f64> {
const INF: &[u8] = b"inf";
// nan = %x6e.61.6e ; nan
pub(crate) fn nan(input: &mut Input<'_>) -> PResult<f64> {
- tag(NAN).value(f64::NAN).parse_next(input)
+ tag(NAN).value(f64::NAN.copysign(1.0)).parse_next(input)
}
const NAN: &[u8] = b"nan";
@@ -319,6 +319,8 @@ pub(crate) const HEXDIG: (RangeInclusive<u8>, RangeInclusive<u8>, RangeInclusive
(DIGIT, b'A'..=b'F', b'a'..=b'f');
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
@@ -353,6 +355,7 @@ mod test {
fn assert_float_eq(actual: f64, expected: f64) {
if expected.is_nan() {
assert!(actual.is_nan());
+ assert_eq!(expected.is_sign_positive(), actual.is_sign_positive());
} else if expected.is_infinite() {
assert!(actual.is_infinite());
assert_eq!(expected.is_sign_positive(), actual.is_sign_positive());
@@ -376,9 +379,9 @@ mod test {
("9_224_617.445_991_228_313", 9_224_617.445_991_227),
("-1.7976931348623157e+308", std::f64::MIN),
("1.7976931348623157e+308", std::f64::MAX),
- ("nan", f64::NAN),
- ("+nan", f64::NAN),
- ("-nan", f64::NAN),
+ ("nan", f64::NAN.copysign(1.0)),
+ ("+nan", f64::NAN.copysign(1.0)),
+ ("-nan", f64::NAN.copysign(-1.0)),
("inf", f64::INFINITY),
("+inf", f64::INFINITY),
("-inf", f64::NEG_INFINITY),
diff --git a/src/parser/state.rs b/src/parser/state.rs
index efa884d..187dd5f 100644
--- a/src/parser/state.rs
+++ b/src/parser/state.rs
@@ -1,5 +1,5 @@
use crate::key::Key;
-use crate::parser::errors::CustomError;
+use crate::parser::error::CustomError;
use crate::repr::Decor;
use crate::table::TableKeyValue;
use crate::{ArrayOfTables, Document, InternalString, Item, RawString, Table};
@@ -39,26 +39,21 @@ impl ParseState {
pub(crate) fn on_keyval(
&mut self,
- mut path: Vec<Key>,
+ path: Vec<Key>,
mut kv: TableKeyValue,
) -> Result<(), CustomError> {
{
let mut prefix = self.trailing.take();
- let first_key = if path.is_empty() {
- &mut kv.key
- } else {
- &mut path[0]
- };
let prefix = match (
prefix.take(),
- first_key.decor.prefix().and_then(|d| d.span()),
+ kv.key.leaf_decor.prefix().and_then(|d| d.span()),
) {
(Some(p), Some(k)) => Some(p.start..k.end),
(Some(p), None) | (None, Some(p)) => Some(p),
(None, None) => None,
};
- first_key
- .decor
+ kv.key
+ .leaf_decor
.set_prefix(prefix.map(RawString::with_span).unwrap_or_default());
}
@@ -94,7 +89,7 @@ impl ParseState {
Ok(())
}
- pub(crate) fn start_aray_table(
+ pub(crate) fn start_array_table(
&mut self,
path: Vec<Key>,
decor: Decor,
@@ -217,9 +212,9 @@ impl ParseState {
Ok(())
}
- pub(crate) fn descend_path<'t, 'k>(
+ pub(crate) fn descend_path<'t>(
mut table: &'t mut Table,
- path: &'k [Key],
+ path: &[Key],
dotted: bool,
) -> Result<&'t mut Table, CustomError> {
for (i, key) in path.iter().enumerate() {
@@ -297,7 +292,7 @@ impl ParseState {
.take()
.map(RawString::with_span)
.unwrap_or_default();
- self.start_aray_table(
+ self.start_array_table(
path,
Decor::new(leading, RawString::with_span(trailing)),
span,
diff --git a/src/parser/strings.rs b/src/parser/strings.rs
index 26f9cc2..675b5c6 100644
--- a/src/parser/strings.rs
+++ b/src/parser/strings.rs
@@ -21,7 +21,7 @@ use winnow::token::tag;
use winnow::token::take_while;
use winnow::trace::trace;
-use crate::parser::errors::CustomError;
+use crate::parser::error::CustomError;
use crate::parser::numbers::HEXDIG;
use crate::parser::prelude::*;
use crate::parser::trivia::{from_utf8_unchecked, newline, ws, ws_newlines, NON_ASCII, WSCHAR};
@@ -363,6 +363,8 @@ fn mll_quotes<'i>(
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
@@ -440,10 +442,10 @@ The quick brown \
#[test]
fn literal_string() {
let inputs = [
- r#"'C:\Users\nodejs\templates'"#,
- r#"'\\ServerX\admin$\system32\'"#,
+ r"'C:\Users\nodejs\templates'",
+ r"'\\ServerX\admin$\system32\'",
r#"'Tom "Dubs" Preston-Werner'"#,
- r#"'<\i\c*\s*>'"#,
+ r"'<\i\c*\s*>'",
];
for input in &inputs {
@@ -456,7 +458,7 @@ The quick brown \
#[test]
fn ml_literal_string() {
let inputs = [
- r#"'''I [dw]on't need \d{2} apples'''"#,
+ r"'''I [dw]on't need \d{2} apples'''",
r#"''''one_quote''''"#,
];
for input in &inputs {
diff --git a/src/parser/trivia.rs b/src/parser/trivia.rs
index a359805..4575fb1 100644
--- a/src/parser/trivia.rs
+++ b/src/parser/trivia.rs
@@ -120,6 +120,8 @@ pub(crate) fn line_trailing(input: &mut Input<'_>) -> PResult<std::ops::Range<us
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
diff --git a/src/parser/value.rs b/src/parser/value.rs
index 14cd951..33300ec 100644
--- a/src/parser/value.rs
+++ b/src/parser/value.rs
@@ -121,6 +121,8 @@ fn apply_raw(mut val: Value, span: std::ops::Range<usize>) -> Result<Value, std:
}
#[cfg(test)]
+#[cfg(feature = "parse")]
+#[cfg(feature = "display")]
mod test {
use super::*;
@@ -131,7 +133,7 @@ mod test {
"-239",
"1e200",
"9_224_617.445_991_228_313",
- r#"'''I [dw]on't need \d{2} apples'''"#,
+ r"'''I [dw]on't need \d{2} apples'''",
r#"'''
The first newline is
trimmed in raw strings.