summaryrefslogtreecommitdiffstats
path: root/vendor/toml_edit/src/error.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/toml_edit/src/error.rs
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/toml_edit/src/error.rs')
-rw-r--r--vendor/toml_edit/src/error.rs246
1 files changed, 246 insertions, 0 deletions
diff --git a/vendor/toml_edit/src/error.rs b/vendor/toml_edit/src/error.rs
new file mode 100644
index 000000000..a98301981
--- /dev/null
+++ b/vendor/toml_edit/src/error.rs
@@ -0,0 +1,246 @@
+use std::error::Error as StdError;
+use std::fmt::{Display, Formatter, Result};
+
+/// 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 {
+ #[cfg(feature = "parse")]
+ pub(crate) fn new(
+ error: winnow::error::ParseError<
+ crate::parser::prelude::Input<'_>,
+ winnow::error::ContextError,
+ >,
+ mut original: crate::parser::prelude::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 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));
+ }
+}