use core::fmt;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "serde")]
use alloc::string::ToString;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
type Message = String;
#[cfg(not(feature = "alloc"))]
type Message = &'static str;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Error {
message: Message,
line: usize,
column: usize,
offset: usize,
#[cfg(feature = "alloc")]
path: Vec<String>,
}
impl Error {
#[cfg(feature = "alloc")]
pub(crate) fn parse(
message: impl Into<String>,
line: usize,
column: usize,
offset: usize,
) -> Self {
Error {
message: message.into(),
line,
column,
offset,
path: Vec::new(),
}
}
#[cfg(feature = "serde")]
pub(crate) fn custom(message: impl Into<String>) -> Self {
Error {
message: message.into(),
line: 0,
column: 0,
offset: 0,
path: Vec::new(),
}
}
pub(crate) fn fixed(message: &'static str) -> Self {
Error {
#[cfg(feature = "alloc")]
message: String::from(message),
#[cfg(not(feature = "alloc"))]
message,
line: 0,
column: 0,
offset: 0,
#[cfg(feature = "alloc")]
path: Vec::new(),
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(not(feature = "serde"), allow(dead_code))]
pub(crate) fn prepend_key(&mut self, key: impl Into<String>) {
self.path.insert(0, key.into());
}
pub fn message(&self) -> &str {
self.message_str()
}
#[cfg(feature = "alloc")]
fn message_str(&self) -> &str {
self.message.as_str()
}
#[cfg(not(feature = "alloc"))]
fn message_str(&self) -> &str {
self.message
}
pub fn line(&self) -> usize {
self.line
}
pub fn column(&self) -> usize {
self.column
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn has_position(&self) -> bool {
self.line != 0
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn key_path(&self) -> Option<String> {
if self.path.is_empty() {
None
} else {
Some(self.path.join("."))
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.has_position() {
return write!(
f,
"TOML parse error at line {}, column {}: {}",
self.line,
self.column,
self.message_str()
);
}
#[cfg(feature = "alloc")]
if let Some(path) = self.key_path() {
return write!(f, "TOML error at `{path}`: {}", self.message_str());
}
f.write_str(self.message_str())
}
}
impl core::error::Error for Error {}
#[cfg(feature = "serde")]
impl ::serde::de::Error for Error {
fn custom<T: fmt::Display>(message: T) -> Error {
Error::custom(message.to_string())
}
}
#[cfg(feature = "serde")]
impl ::serde::ser::Error for Error {
fn custom<T: fmt::Display>(message: T) -> Error {
Error::custom(message.to_string())
}
}