diff options
Diffstat (limited to 'src/parser')
-rw-r--r-- | src/parser/array.rs | 2 | ||||
-rw-r--r-- | src/parser/datetime.rs | 40 | ||||
-rw-r--r-- | src/parser/error.rs | 87 | ||||
-rw-r--r-- | src/parser/errors.rs | 316 | ||||
-rw-r--r-- | src/parser/inline_table.rs | 27 | ||||
-rw-r--r-- | src/parser/key.rs | 36 | ||||
-rw-r--r-- | src/parser/mod.rs | 18 | ||||
-rw-r--r-- | src/parser/numbers.rs | 11 | ||||
-rw-r--r-- | src/parser/state.rs | 23 | ||||
-rw-r--r-- | src/parser/strings.rs | 12 | ||||
-rw-r--r-- | src/parser/trivia.rs | 2 | ||||
-rw-r--r-- | src/parser/value.rs | 4 |
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. |