Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

140
vendor/toml_parser/src/debug.rs vendored Normal file
View File

@@ -0,0 +1,140 @@
use crate::decoder::Encoding;
use crate::ErrorSink;
use crate::Span;
pub(crate) struct DebugDepth(core::sync::atomic::AtomicUsize);
impl DebugDepth {
pub(crate) fn enter_unchecked(&self) -> usize {
self.0.fetch_add(1, core::sync::atomic::Ordering::SeqCst)
}
pub(crate) fn exit_unchecked(&self) {
let _ = self.0.fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
}
pub(crate) fn depth(&self) -> usize {
self.0.load(core::sync::atomic::Ordering::SeqCst)
}
}
static DEBUG_DEPTH: DebugDepth = DebugDepth(core::sync::atomic::AtomicUsize::new(0));
fn render_event(span: impl Into<Option<Span>>, text: &str, style: anstyle::Style) {
#![allow(unexpected_cfgs)] // HACK: fixed in newer versions
let span = span.into();
let depth = DEBUG_DEPTH.depth().min(20);
anstream::eprintln!("{:depth$}{style}{text}: {span:?}{style:#}", "");
}
pub(crate) struct DebugErrorSink<'s> {
sink: &'s mut dyn ErrorSink,
}
impl<'s> DebugErrorSink<'s> {
pub(crate) fn new(sink: &'s mut dyn ErrorSink) -> Self {
Self { sink }
}
}
impl ErrorSink for DebugErrorSink<'_> {
fn report_error(&mut self, error: crate::ParseError) {
render_event(
error.unexpected(),
&format!("{error:?}"),
anstyle::AnsiColor::Red.on_default(),
);
self.sink.report_error(error);
}
}
pub(crate) struct DebugEventReceiver<'r> {
receiver: &'r mut dyn crate::parser::EventReceiver,
}
impl<'r> DebugEventReceiver<'r> {
pub(crate) fn new(receiver: &'r mut dyn crate::parser::EventReceiver) -> Self {
Self { receiver }
}
}
impl crate::parser::EventReceiver for DebugEventReceiver<'_> {
fn std_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_open(span, error);
render_event(span, "[", anstyle::Style::new() | anstyle::Effects::DIMMED);
DEBUG_DEPTH.enter_unchecked();
}
fn std_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_close(span, error);
DEBUG_DEPTH.exit_unchecked();
render_event(span, "]", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn array_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_open(span, error);
render_event(span, "[[", anstyle::Style::new() | anstyle::Effects::DIMMED);
DEBUG_DEPTH.enter_unchecked();
}
fn array_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_close(span, error);
DEBUG_DEPTH.exit_unchecked();
render_event(span, "]]", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn inline_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
let allowed = self.receiver.inline_table_open(span, error);
render_event(span, "{", anstyle::Style::new() | anstyle::Effects::DIMMED);
DEBUG_DEPTH.enter_unchecked();
allowed
}
fn inline_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.inline_table_close(span, error);
DEBUG_DEPTH.exit_unchecked();
render_event(span, "}", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn array_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
let allowed = self.receiver.array_open(span, error);
render_event(span, "[", anstyle::Style::new() | anstyle::Effects::DIMMED);
DEBUG_DEPTH.enter_unchecked();
allowed
}
fn array_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_close(span, error);
DEBUG_DEPTH.exit_unchecked();
render_event(span, "]", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn simple_key(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.simple_key(span, encoding, error);
render_event(span, "<key>", anstyle::AnsiColor::Magenta.on_default());
}
fn key_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_sep(span, error);
render_event(span, ".", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn key_val_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_val_sep(span, error);
render_event(span, "=", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn scalar(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.scalar(span, encoding, error);
render_event(span, "<scalar>", anstyle::AnsiColor::Green.on_default());
}
fn value_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.value_sep(span, error);
render_event(span, ",", anstyle::Style::new() | anstyle::Effects::DIMMED);
}
fn whitespace(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.whitespace(span, error);
render_event(span, "<whitespace>", anstyle::AnsiColor::Cyan.on_default());
}
fn comment(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.comment(span, error);
render_event(span, "<comment>", anstyle::AnsiColor::Cyan.on_default());
}
fn newline(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.newline(span, error);
render_event(span, "<newline>", anstyle::AnsiColor::Cyan.on_default());
}
fn error(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.error(span, error);
render_event(span, "<error>", anstyle::AnsiColor::Red.on_default());
}
}

117
vendor/toml_parser/src/decoder/mod.rs vendored Normal file
View File

@@ -0,0 +1,117 @@
//! Decode [raw][crate::Raw] TOML values into Rust native types
//!
//! See
//! - [`Raw::decode_key`][crate::Raw::decode_key]
//! - [`Raw::decode_scalar`][crate::Raw::decode_scalar]
//! - [`Raw::decode_whitespace`][crate::Raw::decode_whitespace]
//! - [`Raw::decode_comment`][crate::Raw::decode_comment]
//! - [`Raw::decode_newline`][crate::Raw::decode_newline]
#[cfg(feature = "alloc")]
use alloc::borrow::Cow;
#[cfg(feature = "alloc")]
use alloc::string::String;
pub(crate) mod scalar;
pub(crate) mod string;
pub(crate) mod ws;
pub use scalar::IntegerRadix;
pub use scalar::ScalarKind;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[repr(u8)]
pub enum Encoding {
LiteralString = crate::lexer::APOSTROPHE,
BasicString = crate::lexer::QUOTATION_MARK,
MlLiteralString = 1,
MlBasicString,
}
impl Encoding {
pub const fn description(&self) -> &'static str {
match self {
Self::LiteralString => crate::lexer::TokenKind::LiteralString.description(),
Self::BasicString => crate::lexer::TokenKind::BasicString.description(),
Self::MlLiteralString => crate::lexer::TokenKind::MlLiteralString.description(),
Self::MlBasicString => crate::lexer::TokenKind::MlBasicString.description(),
}
}
}
pub trait StringBuilder<'s> {
fn clear(&mut self);
#[must_use]
fn push_str(&mut self, append: &'s str) -> bool;
#[must_use]
fn push_char(&mut self, append: char) -> bool;
}
impl<'s> StringBuilder<'s> for () {
fn clear(&mut self) {}
fn push_str(&mut self, _append: &'s str) -> bool {
true
}
fn push_char(&mut self, _append: char) -> bool {
true
}
}
impl<'s> StringBuilder<'s> for &'s str {
fn clear(&mut self) {
*self = &self[0..0];
}
fn push_str(&mut self, append: &'s str) -> bool {
if self.is_empty() {
*self = append;
true
} else {
false
}
}
fn push_char(&mut self, _append: char) -> bool {
false
}
}
#[cfg(feature = "alloc")]
impl<'s> StringBuilder<'s> for Cow<'s, str> {
fn clear(&mut self) {
match self {
Cow::Borrowed(s) => {
s.clear();
}
Cow::Owned(s) => s.clear(),
}
}
fn push_str(&mut self, append: &'s str) -> bool {
match self {
Cow::Borrowed(s) => {
if !s.push_str(append) {
self.to_mut().push_str(append);
}
}
Cow::Owned(s) => s.push_str(append),
}
true
}
fn push_char(&mut self, append: char) -> bool {
self.to_mut().push(append);
true
}
}
#[cfg(feature = "alloc")]
impl<'s> StringBuilder<'s> for String {
fn clear(&mut self) {
self.clear();
}
fn push_str(&mut self, append: &'s str) -> bool {
self.push_str(append);
true
}
fn push_char(&mut self, append: char) -> bool {
self.push(append);
true
}
}

725
vendor/toml_parser/src/decoder/scalar.rs vendored Normal file
View File

@@ -0,0 +1,725 @@
use winnow::stream::ContainsToken as _;
use winnow::stream::FindSlice as _;
use winnow::stream::Offset as _;
use winnow::stream::Stream as _;
use crate::decoder::StringBuilder;
use crate::ErrorSink;
use crate::Expected;
use crate::ParseError;
use crate::Raw;
use crate::Span;
const ALLOCATION_ERROR: &str = "could not allocate for string";
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum ScalarKind {
String,
Boolean(bool),
DateTime,
Float,
Integer(IntegerRadix),
}
impl ScalarKind {
pub fn description(&self) -> &'static str {
match self {
Self::String => "string",
Self::Boolean(_) => "boolean",
Self::DateTime => "date-time",
Self::Float => "float",
Self::Integer(radix) => radix.description(),
}
}
pub fn invalid_description(&self) -> &'static str {
match self {
Self::String => "invalid string",
Self::Boolean(_) => "invalid boolean",
Self::DateTime => "invalid date-time",
Self::Float => "invalid float",
Self::Integer(radix) => radix.invalid_description(),
}
}
}
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum IntegerRadix {
#[default]
Dec,
Hex,
Oct,
Bin,
}
impl IntegerRadix {
pub fn description(&self) -> &'static str {
match self {
Self::Dec => "integer",
Self::Hex => "hexadecimal",
Self::Oct => "octal",
Self::Bin => "binary",
}
}
pub fn value(&self) -> u32 {
match self {
Self::Dec => 10,
Self::Hex => 16,
Self::Oct => 8,
Self::Bin => 2,
}
}
pub fn invalid_description(&self) -> &'static str {
match self {
Self::Dec => "invalid integer number",
Self::Hex => "invalid hexadecimal number",
Self::Oct => "invalid octal number",
Self::Bin => "invalid binary number",
}
}
fn validator(&self) -> fn(char) -> bool {
match self {
Self::Dec => |c| c.is_ascii_digit(),
Self::Hex => |c| c.is_ascii_hexdigit(),
Self::Oct => |c| matches!(c, '0'..='7'),
Self::Bin => |c| matches!(c, '0'..='1'),
}
}
}
pub(crate) fn decode_unquoted_scalar<'i>(
raw: Raw<'i>,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
let s = raw.as_str();
let Some(first) = s.as_bytes().first() else {
return decode_invalid(raw, output, error);
};
match first {
// number starts
b'+' | b'-' => {
let value = &raw.as_str()[1..];
decode_sign_prefix(raw, value, output, error)
}
// Report as if they were numbers because its most likely a typo
b'_' => decode_datetime_or_float_or_integer(raw.as_str(), raw, output, error),
// Date/number starts
b'0' => decode_zero_prefix(raw.as_str(), false, raw, output, error),
b'1'..=b'9' => decode_datetime_or_float_or_integer(raw.as_str(), raw, output, error),
// Report as if they were numbers because its most likely a typo
b'.' => {
let kind = ScalarKind::Float;
let stream = raw.as_str();
ensure_float(stream, raw, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
b't' | b'T' => {
const SYMBOL: &str = "true";
let kind = ScalarKind::Boolean(true);
let expected = &[Expected::Literal(SYMBOL)];
decode_symbol(raw, SYMBOL, kind, expected, output, error)
}
b'f' | b'F' => {
const SYMBOL: &str = "false";
let kind = ScalarKind::Boolean(false);
let expected = &[Expected::Literal(SYMBOL)];
decode_symbol(raw, SYMBOL, kind, expected, output, error)
}
b'i' | b'I' => {
const SYMBOL: &str = "inf";
let kind = ScalarKind::Float;
let expected = &[Expected::Literal(SYMBOL)];
decode_symbol(raw, SYMBOL, kind, expected, output, error)
}
b'n' | b'N' => {
const SYMBOL: &str = "nan";
let kind = ScalarKind::Float;
let expected = &[Expected::Literal(SYMBOL)];
decode_symbol(raw, SYMBOL, kind, expected, output, error)
}
_ => decode_invalid(raw, output, error),
}
}
pub(crate) fn decode_sign_prefix<'i>(
raw: Raw<'i>,
value: &'i str,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
let Some(first) = value.as_bytes().first() else {
return decode_invalid(raw, output, error);
};
match first {
// number starts
b'+' | b'-' => {
let start = value.offset_from(&raw.as_str());
let end = start + 1;
error.report_error(
ParseError::new("redundant numeric sign")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(start, end)),
);
let value = &value[1..];
decode_sign_prefix(raw, value, output, error)
}
// Report as if they were numbers because its most likely a typo
b'_' => decode_datetime_or_float_or_integer(value, raw, output, error),
// Date/number starts
b'0' => decode_zero_prefix(value, true, raw, output, error),
b'1'..=b'9' => decode_datetime_or_float_or_integer(value, raw, output, error),
// Report as if they were numbers because its most likely a typo
b'.' => {
let kind = ScalarKind::Float;
let stream = raw.as_str();
ensure_float(stream, raw, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
b'i' | b'I' => {
const SYMBOL: &str = "inf";
let kind = ScalarKind::Float;
if value != SYMBOL {
let expected = &[Expected::Literal(SYMBOL)];
let start = value.offset_from(&raw.as_str());
let end = start + value.len();
error.report_error(
ParseError::new(kind.invalid_description())
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(expected)
.with_unexpected(Span::new_unchecked(start, end)),
);
decode_as(raw, SYMBOL, kind, output, error)
} else {
decode_as_is(raw, kind, output, error)
}
}
b'n' | b'N' => {
const SYMBOL: &str = "nan";
let kind = ScalarKind::Float;
if value != SYMBOL {
let expected = &[Expected::Literal(SYMBOL)];
let start = value.offset_from(&raw.as_str());
let end = start + value.len();
error.report_error(
ParseError::new(kind.invalid_description())
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(expected)
.with_unexpected(Span::new_unchecked(start, end)),
);
decode_as(raw, SYMBOL, kind, output, error)
} else {
decode_as_is(raw, kind, output, error)
}
}
_ => decode_invalid(raw, output, error),
}
}
pub(crate) fn decode_zero_prefix<'i>(
value: &'i str,
signed: bool,
raw: Raw<'i>,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
debug_assert_eq!(value.as_bytes()[0], b'0');
if value.len() == 1 {
let kind = ScalarKind::Integer(IntegerRadix::Dec);
// No extra validation needed
decode_float_or_integer(raw.as_str(), raw, kind, output, error)
} else {
let radix = value.as_bytes()[1];
match radix {
b'x' | b'X' => {
if signed {
error.report_error(
ParseError::new("integers with a radix cannot be signed")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, 1)),
);
}
if radix == b'X' {
let start = value.offset_from(&raw.as_str());
let end = start + 2;
error.report_error(
ParseError::new("radix must be lowercase")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal("0x")])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
let radix = IntegerRadix::Hex;
let kind = ScalarKind::Integer(radix);
let stream = &value[2..];
ensure_radixed_value(stream, raw, radix, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
b'o' | b'O' => {
if signed {
error.report_error(
ParseError::new("integers with a radix cannot be signed")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, 1)),
);
}
if radix == b'O' {
let start = value.offset_from(&raw.as_str());
let end = start + 2;
error.report_error(
ParseError::new("radix must be lowercase")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal("0o")])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
let radix = IntegerRadix::Oct;
let kind = ScalarKind::Integer(radix);
let stream = &value[2..];
ensure_radixed_value(stream, raw, radix, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
b'b' | b'B' => {
if signed {
error.report_error(
ParseError::new("integers with a radix cannot be signed")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, 1)),
);
}
if radix == b'B' {
let start = value.offset_from(&raw.as_str());
let end = start + 2;
error.report_error(
ParseError::new("radix must be lowercase")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal("0b")])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
let radix = IntegerRadix::Bin;
let kind = ScalarKind::Integer(radix);
let stream = &value[2..];
ensure_radixed_value(stream, raw, radix, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
b'd' | b'D' => {
if signed {
error.report_error(
ParseError::new("integers with a radix cannot be signed")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, 1)),
);
}
let radix = IntegerRadix::Dec;
let kind = ScalarKind::Integer(radix);
let stream = &value[2..];
error.report_error(
ParseError::new("redundant integer number prefix")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, 2)),
);
ensure_radixed_value(stream, raw, radix, error);
decode_float_or_integer(stream, raw, kind, output, error)
}
_ => decode_datetime_or_float_or_integer(value, raw, output, error),
}
}
}
pub(crate) fn decode_datetime_or_float_or_integer<'i>(
value: &'i str,
raw: Raw<'i>,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
let Some(digit_end) = value
.as_bytes()
.offset_for(|b| !(b'0'..=b'9').contains_token(b))
else {
let kind = ScalarKind::Integer(IntegerRadix::Dec);
let stream = raw.as_str();
ensure_no_leading_zero(value, raw, error);
return decode_float_or_integer(stream, raw, kind, output, error);
};
#[cfg(feature = "unsafe")] // SAFETY: ascii digits ensures UTF-8 boundary
let rest = unsafe { &value.get_unchecked(digit_end..) };
#[cfg(not(feature = "unsafe"))]
let rest = &value[digit_end..];
if rest.starts_with("-") || rest.starts_with(":") {
decode_as_is(raw, ScalarKind::DateTime, output, error)
} else if rest.contains(" ") {
decode_invalid(raw, output, error)
} else if is_float(rest) {
let kind = ScalarKind::Float;
let stream = raw.as_str();
ensure_float(value, raw, error);
decode_float_or_integer(stream, raw, kind, output, error)
} else if rest.starts_with("_") {
let kind = ScalarKind::Integer(IntegerRadix::Dec);
let stream = raw.as_str();
ensure_no_leading_zero(value, raw, error);
decode_float_or_integer(stream, raw, kind, output, error)
} else {
decode_invalid(raw, output, error)
}
}
/// ```abnf
/// float = float-int-part ( exp / frac [ exp ] )
///
/// float-int-part = dec-int
/// frac = decimal-point zero-prefixable-int
/// decimal-point = %x2E ; .
/// zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT )
///
/// exp = "e" float-exp-part
/// float-exp-part = [ minus / plus ] zero-prefixable-int
/// ```
pub(crate) fn ensure_float<'i>(mut value: &'i str, raw: Raw<'i>, error: &mut dyn ErrorSink) {
ensure_dec_uint(&mut value, raw, false, "invalid mantissa", error);
if value.starts_with(".") {
let _ = value.next_token();
ensure_dec_uint(&mut value, raw, true, "invalid fraction", error);
}
if value.starts_with(['e', 'E']) {
let _ = value.next_token();
if value.starts_with(['+', '-']) {
let _ = value.next_token();
}
ensure_dec_uint(&mut value, raw, true, "invalid exponent", error);
}
if !value.is_empty() {
let start = value.offset_from(&raw.as_str());
let end = raw.len();
error.report_error(
ParseError::new(ScalarKind::Float.invalid_description())
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
}
pub(crate) fn ensure_dec_uint<'i>(
value: &mut &'i str,
raw: Raw<'i>,
zero_prefix: bool,
invalid_description: &'static str,
error: &mut dyn ErrorSink,
) {
let start = *value;
let mut digit_count = 0;
while let Some(current) = value.chars().next() {
if current.is_ascii_digit() {
digit_count += 1;
} else if current == '_' {
} else {
break;
}
let _ = value.next_token();
}
match digit_count {
0 => {
let start = start.offset_from(&raw.as_str());
let end = start;
error.report_error(
ParseError::new(invalid_description)
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Description("digits")])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
1 => {}
_ if start.starts_with("0") && !zero_prefix => {
let start = start.offset_from(&raw.as_str());
let end = start + 1;
error.report_error(
ParseError::new("unexpected leading zero")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
_ => {}
}
}
pub(crate) fn ensure_no_leading_zero<'i>(value: &'i str, raw: Raw<'i>, error: &mut dyn ErrorSink) {
if value.starts_with("0") {
let start = value.offset_from(&raw.as_str());
let end = start + 1;
error.report_error(
ParseError::new("unexpected leading zero")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(start, end)),
);
}
}
pub(crate) fn ensure_radixed_value(
value: &str,
raw: Raw<'_>,
radix: IntegerRadix,
error: &mut dyn ErrorSink,
) {
let invalid = ['+', '-'];
let value = if let Some(value) = value.strip_prefix(invalid) {
let pos = raw.as_str().find(invalid).unwrap();
error.report_error(
ParseError::new("unexpected sign")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(pos, pos + 1)),
);
value
} else {
value
};
let valid = radix.validator();
for (index, c) in value.char_indices() {
if !valid(c) && c != '_' {
let pos = value.offset_from(&raw.as_str()) + index;
error.report_error(
ParseError::new(radix.invalid_description())
.with_context(Span::new_unchecked(0, raw.len()))
.with_unexpected(Span::new_unchecked(pos, pos)),
);
}
}
}
pub(crate) fn decode_float_or_integer<'i>(
stream: &'i str,
raw: Raw<'i>,
kind: ScalarKind,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
output.clear();
let underscore = "_";
if has_underscore(stream) {
if stream.starts_with(underscore) {
error.report_error(
ParseError::new("`_` may only go between digits")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(0, underscore.len())),
);
}
if 1 < stream.len() && stream.ends_with(underscore) {
let start = stream.offset_from(&raw.as_str());
let end = start + stream.len();
error.report_error(
ParseError::new("`_` may only go between digits")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[])
.with_unexpected(Span::new_unchecked(end - underscore.len(), end)),
);
}
for part in stream.split(underscore) {
let part_start = part.offset_from(&raw.as_str());
let part_end = part_start + part.len();
if 0 < part_start {
let first = part.as_bytes().first().copied().unwrap_or(b'0');
if !is_any_digit(first, kind) {
let start = part_start - 1;
let end = part_start;
debug_assert_eq!(&raw.as_str()[start..end], underscore);
error.report_error(
ParseError::new("`_` may only go between digits")
.with_context(Span::new_unchecked(0, raw.len()))
.with_unexpected(Span::new_unchecked(start, end)),
);
}
}
if 1 < part.len() && part_end < raw.len() {
let last = part.as_bytes().last().copied().unwrap_or(b'0');
if !is_any_digit(last, kind) {
let start = part_end;
let end = start + underscore.len();
debug_assert_eq!(&raw.as_str()[start..end], underscore);
error.report_error(
ParseError::new("`_` may only go between digits")
.with_context(Span::new_unchecked(0, raw.len()))
.with_unexpected(Span::new_unchecked(start, end)),
);
}
}
if part.is_empty() && part_start != 0 && part_end != raw.len() {
let start = part_start;
let end = start + 1;
error.report_error(
ParseError::new("`_` may only go between digits")
.with_context(Span::new_unchecked(0, raw.len()))
.with_unexpected(Span::new_unchecked(start, end)),
);
}
if !part.is_empty() && !output.push_str(part) {
error.report_error(
ParseError::new(ALLOCATION_ERROR)
.with_unexpected(Span::new_unchecked(part_start, part_end)),
);
}
}
} else {
if !output.push_str(stream) {
error.report_error(
ParseError::new(ALLOCATION_ERROR)
.with_unexpected(Span::new_unchecked(0, raw.len())),
);
}
}
kind
}
fn is_any_digit(b: u8, kind: ScalarKind) -> bool {
if kind == ScalarKind::Float {
is_dec_integer_digit(b)
} else {
is_any_integer_digit(b)
}
}
fn is_any_integer_digit(b: u8) -> bool {
(b'0'..=b'9', b'a'..=b'f', b'A'..=b'F').contains_token(b)
}
fn is_dec_integer_digit(b: u8) -> bool {
(b'0'..=b'9').contains_token(b)
}
fn has_underscore(raw: &str) -> bool {
raw.as_bytes().find_slice(b'_').is_some()
}
fn is_float(raw: &str) -> bool {
raw.as_bytes().find_slice((b'.', b'e', b'E')).is_some()
}
pub(crate) fn decode_as_is<'i>(
raw: Raw<'i>,
kind: ScalarKind,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
let kind = decode_as(raw, raw.as_str(), kind, output, error);
kind
}
pub(crate) fn decode_as<'i>(
raw: Raw<'i>,
symbol: &'i str,
kind: ScalarKind,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
output.clear();
if !output.push_str(symbol) {
error.report_error(
ParseError::new(ALLOCATION_ERROR).with_unexpected(Span::new_unchecked(0, raw.len())),
);
}
kind
}
pub(crate) fn decode_symbol<'i>(
raw: Raw<'i>,
symbol: &'static str,
kind: ScalarKind,
expected: &'static [Expected],
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
if raw.as_str() != symbol {
if raw.as_str().contains(" ") {
return decode_invalid(raw, output, error);
} else {
error.report_error(
ParseError::new(kind.invalid_description())
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(expected)
.with_unexpected(Span::new_unchecked(0, raw.len())),
);
}
}
decode_as(raw, symbol, kind, output, error)
}
pub(crate) fn decode_invalid<'i>(
raw: Raw<'i>,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> ScalarKind {
if raw.as_str().ends_with("'''") {
error.report_error(
ParseError::new("missing opening quote")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal(r#"'''"#)])
.with_unexpected(Span::new_unchecked(0, 0)),
);
} else if raw.as_str().ends_with(r#"""""#) {
error.report_error(
ParseError::new("missing opening quote")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Description("multi-line basic string")])
.with_expected(&[Expected::Literal(r#"""""#)])
.with_unexpected(Span::new_unchecked(0, 0)),
);
} else if raw.as_str().ends_with("'") {
error.report_error(
ParseError::new("missing opening quote")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal(r#"'"#)])
.with_unexpected(Span::new_unchecked(0, 0)),
);
} else if raw.as_str().ends_with(r#"""#) {
error.report_error(
ParseError::new("missing opening quote")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal(r#"""#)])
.with_unexpected(Span::new_unchecked(0, 0)),
);
} else {
error.report_error(
ParseError::new("string values must be quoted")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Description("literal string")])
.with_unexpected(Span::new_unchecked(0, raw.len())),
);
}
output.clear();
if !output.push_str(raw.as_str()) {
error.report_error(
ParseError::new(ALLOCATION_ERROR).with_unexpected(Span::new_unchecked(0, raw.len())),
);
}
ScalarKind::String
}

1265
vendor/toml_parser/src/decoder/string.rs vendored Normal file

File diff suppressed because it is too large Load Diff

76
vendor/toml_parser/src/decoder/ws.rs vendored Normal file
View File

@@ -0,0 +1,76 @@
use core::ops::RangeInclusive;
use winnow::stream::ContainsToken as _;
use crate::lexer::COMMENT_START_SYMBOL;
use crate::ErrorSink;
use crate::Expected;
use crate::ParseError;
use crate::Raw;
use crate::Span;
/// Parse comment
///
/// ```bnf
/// ;; Comment
///
/// comment-start-symbol = %x23 ; #
/// non-ascii = %x80-D7FF / %xE000-10FFFF
/// non-eol = %x09 / %x20-7F / non-ascii
///
/// comment = comment-start-symbol *non-eol
/// ```
pub(crate) fn decode_comment(raw: Raw<'_>, error: &mut dyn ErrorSink) {
let s = raw.as_bytes();
if s.first() != Some(&COMMENT_START_SYMBOL) {
error.report_error(
ParseError::new("missing comment start")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal("#")])
.with_unexpected(Span::new_unchecked(0, 0)),
);
}
for (i, b) in s.iter().copied().enumerate() {
if !NON_EOL.contains_token(b) {
error.report_error(
ParseError::new("invalid comment character")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Description("printable characters")])
.with_unexpected(Span::new_unchecked(i, i)),
);
}
}
}
// non-ascii = %x80-D7FF / %xE000-10FFFF
// - ASCII is 0xxxxxxx
// - First byte for UTF-8 is 11xxxxxx
// - Subsequent UTF-8 bytes are 10xxxxxx
pub(crate) const NON_ASCII: RangeInclusive<u8> = 0x80..=0xff;
// non-eol = %x09 / %x20-7E / non-ascii
pub(crate) const NON_EOL: (u8, RangeInclusive<u8>, RangeInclusive<u8>) =
(0x09, 0x20..=0x7E, NON_ASCII);
/// Parse newline
///
/// ```bnf
///;; Newline
///
/// newline = %x0A ; LF
/// newline =/ %x0D.0A ; CRLF
/// ```
pub(crate) fn decode_newline(raw: Raw<'_>, error: &mut dyn ErrorSink) {
let s = raw.as_str();
if s == "\r" {
error.report_error(
ParseError::new("carriage return must be followed by newline")
.with_context(Span::new_unchecked(0, raw.len()))
.with_expected(&[Expected::Literal("\n")])
.with_unexpected(Span::new_unchecked(raw.len(), raw.len())),
);
}
}

102
vendor/toml_parser/src/error.rs vendored Normal file
View File

@@ -0,0 +1,102 @@
use crate::Span;
pub trait ErrorSink {
fn report_error(&mut self, error: ParseError);
}
impl<F> ErrorSink for F
where
F: FnMut(ParseError),
{
fn report_error(&mut self, error: ParseError) {
(self)(error);
}
}
impl ErrorSink for () {
fn report_error(&mut self, _error: ParseError) {}
}
impl ErrorSink for Option<ParseError> {
fn report_error(&mut self, error: ParseError) {
self.get_or_insert(error);
}
}
#[cfg(feature = "alloc")]
#[allow(unused_qualifications)]
impl ErrorSink for alloc::vec::Vec<ParseError> {
fn report_error(&mut self, error: ParseError) {
self.push(error);
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[non_exhaustive]
pub struct ParseError {
context: Option<Span>,
description: ErrorStr,
expected: Option<&'static [Expected]>,
unexpected: Option<Span>,
}
impl ParseError {
pub fn new(description: impl Into<ErrorStr>) -> Self {
Self {
context: None,
description: description.into(),
expected: None,
unexpected: None,
}
}
pub fn with_context(mut self, context: Span) -> Self {
self.context = Some(context);
self
}
pub fn with_expected(mut self, expected: &'static [Expected]) -> Self {
self.expected = Some(expected);
self
}
pub fn with_unexpected(mut self, unexpected: Span) -> Self {
self.unexpected = Some(unexpected);
self
}
pub fn context(&self) -> Option<Span> {
self.context
}
pub fn description(&self) -> &str {
&self.description
}
pub fn expected(&self) -> Option<&'static [Expected]> {
self.expected
}
pub fn unexpected(&self) -> Option<Span> {
self.unexpected
}
pub(crate) fn rebase_spans(mut self, offset: usize) -> Self {
if let Some(context) = self.context.as_mut() {
*context += offset;
}
if let Some(unexpected) = self.unexpected.as_mut() {
*unexpected += offset;
}
self
}
}
#[cfg(feature = "alloc")]
type ErrorStr = alloc::borrow::Cow<'static, str>;
#[cfg(not(feature = "alloc"))]
type ErrorStr = &'static str;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[non_exhaustive]
pub enum Expected {
Literal(&'static str),
Description(&'static str),
}

627
vendor/toml_parser/src/lexer/mod.rs vendored Normal file
View File

@@ -0,0 +1,627 @@
//! Lex TOML tokens
//!
//! To get started, see [`Source::lex`][crate::Source::lex]
#[cfg(test)]
#[cfg(feature = "std")]
mod test;
mod token;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use winnow::stream::AsBStr as _;
use winnow::stream::ContainsToken as _;
use winnow::stream::FindSlice as _;
use winnow::stream::Location;
use winnow::stream::Stream as _;
use crate::Span;
pub use token::Token;
pub use token::TokenKind;
/// Lex TOML [tokens][Token]
///
/// To get started, see [`Source::lex`][crate::Source::lex]
pub struct Lexer<'i> {
stream: Stream<'i>,
eof: bool,
}
impl<'i> Lexer<'i> {
pub(crate) fn new(input: &'i str) -> Self {
let mut stream = Stream::new(input);
if input.as_bytes().starts_with(BOM) {
let offset = BOM.len();
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
}
Lexer { stream, eof: false }
}
#[cfg(feature = "alloc")]
pub fn into_vec(self) -> Vec<Token> {
#![allow(unused_qualifications)] // due to MSRV of 1.66
let capacity = core::cmp::min(
self.stream.len(),
usize::MAX / core::mem::size_of::<Token>(),
);
let mut vec = Vec::with_capacity(capacity);
vec.extend(self);
vec
}
}
impl Iterator for Lexer<'_> {
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
let Some(peek_byte) = self.stream.as_bstr().first() else {
if self.eof {
return None;
} else {
self.eof = true;
let start = self.stream.current_token_start();
let span = Span::new_unchecked(start, start);
return Some(Token::new(TokenKind::Eof, span));
}
};
Some(process_token(*peek_byte, &mut self.stream))
}
}
const BOM: &[u8] = b"\xEF\xBB\xBF";
pub(crate) type Stream<'i> = winnow::stream::LocatingSlice<&'i str>;
fn process_token(peek_byte: u8, stream: &mut Stream<'_>) -> Token {
let token = match peek_byte {
b'.' => lex_ascii_char(stream, TokenKind::Dot),
b'=' => lex_ascii_char(stream, TokenKind::Equals),
b',' => lex_ascii_char(stream, TokenKind::Comma),
b'[' => lex_ascii_char(stream, TokenKind::LeftSquareBracket),
b']' => lex_ascii_char(stream, TokenKind::RightSquareBracket),
b'{' => lex_ascii_char(stream, TokenKind::LeftCurlyBracket),
b'}' => lex_ascii_char(stream, TokenKind::RightCurlyBracket),
b' ' => lex_whitespace(stream),
b'\t' => lex_whitespace(stream),
b'#' => lex_comment(stream),
b'\r' => lex_crlf(stream),
b'\n' => lex_ascii_char(stream, TokenKind::Newline),
b'\'' => {
if stream.starts_with(ML_LITERAL_STRING_DELIM) {
lex_ml_literal_string(stream)
} else {
lex_literal_string(stream)
}
}
b'"' => {
if stream.starts_with(ML_BASIC_STRING_DELIM) {
lex_ml_basic_string(stream)
} else {
lex_basic_string(stream)
}
}
_ => lex_atom(stream),
};
token
}
/// Process an ASCII character token
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream` must be non-empty
/// - `stream[0]` must be ASCII
fn lex_ascii_char(stream: &mut Stream<'_>, kind: TokenKind) -> Token {
debug_assert!(!stream.is_empty());
let start = stream.current_token_start();
let offset = 1; // an ascii character
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(kind, span)
}
/// Process Whitespace
///
/// ```bnf
/// ;; Whitespace
///
/// ws = *wschar
/// wschar = %x20 ; Space
/// wschar =/ %x09 ; Horizontal tab
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream` must be non-empty
fn lex_whitespace(stream: &mut Stream<'_>) -> Token {
debug_assert!(!stream.is_empty());
let start = stream.current_token_start();
let offset = stream
.as_bstr()
.offset_for(|b| !WSCHAR.contains_token(b))
.unwrap_or(stream.eof_offset());
#[cfg(feature = "unsafe")] // SAFETY: WSCHAR ensures `offset` will be at UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::Whitespace, span)
}
/// ```bnf
/// wschar = %x20 ; Space
/// wschar =/ %x09 ; Horizontal tab
/// ```
pub(crate) const WSCHAR: (u8, u8) = (b' ', b'\t');
/// Process Comment
///
/// ```bnf
/// ;; Comment
///
/// comment-start-symbol = %x23 ; #
/// non-ascii = %x80-D7FF / %xE000-10FFFF
/// non-eol = %x09 / %x20-7F / non-ascii
///
/// comment = comment-start-symbol *non-eol
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream[0] == b'#'`
fn lex_comment(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let offset = stream
.as_bytes()
.find_slice((b'\r', b'\n'))
.map(|s| s.start)
.unwrap_or_else(|| stream.eof_offset());
#[cfg(feature = "unsafe")] // SAFETY: newlines ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::Comment, span)
}
/// `comment-start-symbol = %x23 ; #`
pub(crate) const COMMENT_START_SYMBOL: u8 = b'#';
/// Process Newline
///
/// ```bnf
/// ;; Newline
///
/// newline = %x0A ; LF
/// newline =/ %x0D.0A ; CRLF
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream[0] == b'\r'`
fn lex_crlf(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let mut offset = '\r'.len_utf8();
let has_lf = stream.as_bstr().get(1) == Some(&b'\n');
if has_lf {
offset += '\n'.len_utf8();
}
#[cfg(feature = "unsafe")] // SAFETY: newlines ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::Newline, span)
}
/// Process literal string
///
/// ```bnf
/// ;; Literal String
///
/// literal-string = apostrophe *literal-char apostrophe
///
/// apostrophe = %x27 ; ' apostrophe
///
/// literal-char = %x09 / %x20-26 / %x28-7E / non-ascii
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream[0] == b'\''`
fn lex_literal_string(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let offset = 1; // APOSTROPHE
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let offset = match stream.as_bstr().find_slice((APOSTROPHE, b'\n')) {
Some(span) => {
if stream.as_bstr()[span.start] == APOSTROPHE {
span.end
} else {
span.start
}
}
None => stream.eof_offset(),
};
#[cfg(feature = "unsafe")]
// SAFETY: `APOSTROPHE`/newline ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::LiteralString, span)
}
/// `apostrophe = %x27 ; ' apostrophe`
pub(crate) const APOSTROPHE: u8 = b'\'';
/// Process multi-line literal string
///
/// ```bnf
/// ;; Multiline Literal String
///
/// ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
/// ml-literal-string-delim
/// ml-literal-string-delim = 3apostrophe
/// ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ]
///
/// mll-content = mll-char / newline
/// mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
/// mll-quotes = 1*2apostrophe
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream.starts_with(ML_LITERAL_STRING_DELIM)`
fn lex_ml_literal_string(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let offset = ML_LITERAL_STRING_DELIM.len();
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let offset = match stream.as_bstr().find_slice(ML_LITERAL_STRING_DELIM) {
Some(span) => span.end,
None => stream.eof_offset(),
};
#[cfg(feature = "unsafe")]
// SAFETY: `ML_LITERAL_STRING_DELIM` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
if stream.as_bstr().peek_token() == Some(APOSTROPHE) {
let offset = 1;
#[cfg(feature = "unsafe")] // SAFETY: `APOSTROPHE` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
if stream.as_bstr().peek_token() == Some(APOSTROPHE) {
let offset = 1;
#[cfg(feature = "unsafe")]
// SAFETY: `APOSTROPHE` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
}
}
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::MlLiteralString, span)
}
/// `ml-literal-string-delim = 3apostrophe`
pub(crate) const ML_LITERAL_STRING_DELIM: &str = "'''";
/// Process basic string
///
/// ```bnf
/// ;; Basic String
///
/// basic-string = quotation-mark *basic-char quotation-mark
///
/// quotation-mark = %x22 ; "
///
/// basic-char = basic-unescaped / escaped
/// basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
/// escaped = escape escape-seq-char
///
/// escape = %x5C ; \
/// escape-seq-char = %x22 ; " quotation mark U+0022
/// escape-seq-char =/ %x5C ; \ reverse solidus U+005C
/// escape-seq-char =/ %x62 ; b backspace U+0008
/// escape-seq-char =/ %x66 ; f form feed U+000C
/// escape-seq-char =/ %x6E ; n line feed U+000A
/// escape-seq-char =/ %x72 ; r carriage return U+000D
/// escape-seq-char =/ %x74 ; t tab U+0009
/// escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX
/// escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream[0] == b'"'`
fn lex_basic_string(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let offset = 1; // QUOTATION_MARK
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
loop {
// newline is present for error recovery
match stream.as_bstr().find_slice((QUOTATION_MARK, ESCAPE, b'\n')) {
Some(span) => {
let found = stream.as_bstr()[span.start];
if found == QUOTATION_MARK {
let offset = span.end;
#[cfg(feature = "unsafe")]
// SAFETY: `QUOTATION_MARK` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
break;
} else if found == ESCAPE {
let offset = span.end;
#[cfg(feature = "unsafe")]
// SAFETY: `ESCAPE` / newline ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let peek = stream.as_bstr().peek_token();
match peek {
Some(ESCAPE) | Some(QUOTATION_MARK) => {
let offset = 1; // ESCAPE / QUOTATION_MARK
#[cfg(feature = "unsafe")]
#[cfg(feature = "unsafe")]
// SAFETY: `ESCAPE` / newline ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
}
_ => {}
}
continue;
} else if found == b'\n' {
let offset = span.start;
#[cfg(feature = "unsafe")]
// SAFETY: newline ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
break;
} else {
unreachable!("found `{found}`");
}
}
None => {
stream.finish();
break;
}
}
}
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::BasicString, span)
}
/// `quotation-mark = %x22 ; "`
pub(crate) const QUOTATION_MARK: u8 = b'"';
/// `escape = %x5C ; \`
pub(crate) const ESCAPE: u8 = b'\\';
/// Process multi-line basic string
///
/// ```bnf
/// ;; Multiline Basic String
///
/// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
/// ml-basic-string-delim
/// ml-basic-string-delim = 3quotation-mark
/// ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
///
/// mlb-content = mlb-char / newline / mlb-escaped-nl
/// mlb-char = mlb-unescaped / escaped
/// mlb-quotes = 1*2quotation-mark
/// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
/// mlb-escaped-nl = escape ws newline *( wschar / newline )
/// ```
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream.starts_with(ML_BASIC_STRING_DELIM)`
fn lex_ml_basic_string(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
let offset = ML_BASIC_STRING_DELIM.len();
#[cfg(feature = "unsafe")] // SAFETY: only called when next character is ASCII
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
loop {
// newline is present for error recovery
match stream.as_bstr().find_slice((ML_BASIC_STRING_DELIM, "\\")) {
Some(span) => {
let found = stream.as_bstr()[span.start];
if found == QUOTATION_MARK {
let offset = span.end;
#[cfg(feature = "unsafe")]
// SAFETY: `QUOTATION_MARK` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
break;
} else if found == ESCAPE {
let offset = span.end;
#[cfg(feature = "unsafe")]
// SAFETY: `ESCAPE` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let peek = stream.as_bstr().peek_token();
match peek {
Some(ESCAPE) | Some(QUOTATION_MARK) => {
let offset = 1; // ESCAPE / QUOTATION_MARK
#[cfg(feature = "unsafe")]
// SAFETY: `QUOTATION_MARK`/`ESCAPE` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
}
_ => {}
}
continue;
} else {
unreachable!("found `{found}`");
}
}
None => {
stream.finish();
break;
}
}
}
if stream.as_bstr().peek_token() == Some(QUOTATION_MARK) {
let offset = 1;
#[cfg(feature = "unsafe")]
// SAFETY: `QUOTATION_MARK` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
if stream.as_bstr().peek_token() == Some(QUOTATION_MARK) {
let offset = 1;
#[cfg(feature = "unsafe")]
// SAFETY: `QUOTATION_MARK` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
}
}
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::MlBasicString, span)
}
/// `ml-basic-string-delim = 3quotation-mark`
pub(crate) const ML_BASIC_STRING_DELIM: &str = "\"\"\"";
/// Process Atom
///
/// This is everything else
///
/// # Safety
///
/// - `stream` must be UTF-8
/// - `stream` must be non-empty
fn lex_atom(stream: &mut Stream<'_>) -> Token {
let start = stream.current_token_start();
// Intentionally leaves off quotes in case the opening quote was missing
const TOKEN_START: &[u8] = b".=,[]{} \t#\r\n";
let offset = stream
.as_bstr()
.offset_for(|b| TOKEN_START.contains_token(b))
.unwrap_or_else(|| stream.eof_offset());
#[cfg(feature = "unsafe")] // SAFETY: `TOKEN_START` ensure `offset` is along UTF-8 boundary
unsafe {
stream.next_slice_unchecked(offset)
};
#[cfg(not(feature = "unsafe"))]
stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end);
Token::new(TokenKind::Atom, span)
}

1700
vendor/toml_parser/src/lexer/test.rs vendored Normal file

File diff suppressed because it is too large Load Diff

106
vendor/toml_parser/src/lexer/token.rs vendored Normal file
View File

@@ -0,0 +1,106 @@
//! Lexed TOML tokens
use super::Span;
use super::APOSTROPHE;
use super::COMMENT_START_SYMBOL;
use super::QUOTATION_MARK;
use super::WSCHAR;
use crate::decoder::Encoding;
/// An unvalidated TOML Token
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Token {
pub(super) kind: TokenKind,
pub(super) span: Span,
}
impl Token {
pub(super) fn new(kind: TokenKind, span: Span) -> Self {
Self { kind, span }
}
#[inline(always)]
pub fn kind(&self) -> TokenKind {
self.kind
}
#[inline(always)]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[repr(u8)]
pub enum TokenKind {
/// Either for dotted-key or float
Dot = b'.',
/// Key-value separator
Equals = b'=',
/// Value separator
Comma = b',',
/// Either array or standard-table start
LeftSquareBracket = b'[',
/// Either array or standard-table end
RightSquareBracket = b']',
/// Inline table start
LeftCurlyBracket = b'{',
/// Inline table end
RightCurlyBracket = b'}',
Whitespace = WSCHAR.0,
Comment = COMMENT_START_SYMBOL,
Newline = b'\n',
LiteralString = APOSTROPHE,
BasicString = QUOTATION_MARK,
MlLiteralString = 1,
MlBasicString,
/// Anything else
Atom,
Eof,
}
impl TokenKind {
pub const fn description(&self) -> &'static str {
match self {
Self::Dot => "`.`",
Self::Equals => "`=`",
Self::Comma => "`,`",
Self::LeftSquareBracket => "`[`",
Self::RightSquareBracket => "`]`",
Self::LeftCurlyBracket => "`{`",
Self::RightCurlyBracket => "`}`",
Self::Whitespace => "whitespace",
Self::Comment => "comment",
Self::Newline => "newline",
Self::LiteralString => "literal string",
Self::BasicString => "basic string",
Self::MlLiteralString => "multi-line literal string",
Self::MlBasicString => "multi-line basic string",
Self::Atom => "token",
Self::Eof => "end-of-input",
}
}
pub fn encoding(&self) -> Option<Encoding> {
match self {
Self::LiteralString => Some(Encoding::LiteralString),
Self::BasicString => Some(Encoding::BasicString),
Self::MlLiteralString => Some(Encoding::MlLiteralString),
Self::MlBasicString => Some(Encoding::MlBasicString),
Self::Atom
| Self::LeftSquareBracket
| Self::RightSquareBracket
| Self::Dot
| Self::Equals
| Self::Comma
| Self::RightCurlyBracket
| Self::LeftCurlyBracket
| Self::Whitespace
| Self::Newline
| Self::Comment
| Self::Eof => None,
}
}
}

49
vendor/toml_parser/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,49 @@
//! TOML lexer and parser
//!
//! Characteristics:
//! - Error recovery
//! - Lazy validation
//! - `forbid(unsafe)` by default, requiring the `unsafe` feature otherwise
//! - `no_std` support, including putting users in charge of allocation choices (including not
//! allocating)
//!
//! Full parsing is broken into three phases:
//! 1. [Lexing tokens][lexer]
//! 2. [Parsing tokens][parser] (push parser)
//! 3. Organizing the physical layout into the logical layout,
//! including [decoding keys and values][decoder]
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(not(feature = "unsafe"), forbid(unsafe_code))]
#![warn(clippy::std_instead_of_core)]
#![warn(clippy::std_instead_of_alloc)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[macro_use]
mod macros;
#[cfg(feature = "debug")]
pub(crate) mod debug;
mod error;
mod source;
pub mod decoder;
pub mod lexer;
pub mod parser;
pub use error::ErrorSink;
pub use error::Expected;
pub use error::ParseError;
pub use source::Raw;
pub use source::Source;
pub use source::SourceIndex;
pub use source::Span;
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;

1
vendor/toml_parser/src/macros.rs vendored Normal file
View File

@@ -0,0 +1 @@

1641
vendor/toml_parser/src/parser/document.rs vendored Normal file

File diff suppressed because it is too large Load Diff

543
vendor/toml_parser/src/parser/event.rs vendored Normal file
View File

@@ -0,0 +1,543 @@
use crate::decoder::Encoding;
use crate::ErrorSink;
use crate::ParseError;
use crate::Source;
use crate::Span;
pub trait EventReceiver {
fn std_table_open(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn std_table_close(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn array_table_open(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn array_table_close(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
/// Returns if entering the inline table is allowed
#[must_use]
fn inline_table_open(&mut self, _span: Span, _error: &mut dyn ErrorSink) -> bool {
true
}
fn inline_table_close(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
/// Returns if entering the array is allowed
#[must_use]
fn array_open(&mut self, _span: Span, _error: &mut dyn ErrorSink) -> bool {
true
}
fn array_close(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn simple_key(&mut self, _span: Span, _kind: Option<Encoding>, _error: &mut dyn ErrorSink) {}
fn key_sep(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn key_val_sep(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn scalar(&mut self, _span: Span, _kind: Option<Encoding>, _error: &mut dyn ErrorSink) {}
fn value_sep(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn whitespace(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn comment(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn newline(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
fn error(&mut self, _span: Span, _error: &mut dyn ErrorSink) {}
}
impl<F> EventReceiver for F
where
F: FnMut(Event),
{
fn std_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::StdTableOpen,
encoding: None,
span,
});
}
fn std_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::StdTableClose,
encoding: None,
span,
});
}
fn array_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::ArrayTableOpen,
encoding: None,
span,
});
}
fn array_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::ArrayTableClose,
encoding: None,
span,
});
}
fn inline_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) -> bool {
(self)(Event {
kind: EventKind::InlineTableOpen,
encoding: None,
span,
});
true
}
fn inline_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::InlineTableClose,
encoding: None,
span,
});
}
fn array_open(&mut self, span: Span, _error: &mut dyn ErrorSink) -> bool {
(self)(Event {
kind: EventKind::ArrayOpen,
encoding: None,
span,
});
true
}
fn array_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::ArrayClose,
encoding: None,
span,
});
}
fn simple_key(&mut self, span: Span, encoding: Option<Encoding>, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::SimpleKey,
encoding,
span,
});
}
fn key_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::KeySep,
encoding: None,
span,
});
}
fn key_val_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::KeyValSep,
encoding: None,
span,
});
}
fn scalar(&mut self, span: Span, encoding: Option<Encoding>, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::Scalar,
encoding,
span,
});
}
fn value_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::ValueSep,
encoding: None,
span,
});
}
fn whitespace(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::Whitespace,
encoding: None,
span,
});
}
fn comment(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::Comment,
encoding: None,
span,
});
}
fn newline(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::Newline,
encoding: None,
span,
});
}
fn error(&mut self, span: Span, _error: &mut dyn ErrorSink) {
(self)(Event {
kind: EventKind::Error,
encoding: None,
span,
});
}
}
#[cfg(feature = "alloc")]
#[allow(unused_qualifications)]
impl EventReceiver for alloc::vec::Vec<Event> {
fn std_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::StdTableOpen,
encoding: None,
span,
});
}
fn std_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::StdTableClose,
encoding: None,
span,
});
}
fn array_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::ArrayTableOpen,
encoding: None,
span,
});
}
fn array_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::ArrayTableClose,
encoding: None,
span,
});
}
fn inline_table_open(&mut self, span: Span, _error: &mut dyn ErrorSink) -> bool {
self.push(Event {
kind: EventKind::InlineTableOpen,
encoding: None,
span,
});
true
}
fn inline_table_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::InlineTableClose,
encoding: None,
span,
});
}
fn array_open(&mut self, span: Span, _error: &mut dyn ErrorSink) -> bool {
self.push(Event {
kind: EventKind::ArrayOpen,
encoding: None,
span,
});
true
}
fn array_close(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::ArrayClose,
encoding: None,
span,
});
}
fn simple_key(&mut self, span: Span, encoding: Option<Encoding>, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::SimpleKey,
encoding,
span,
});
}
fn key_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::KeySep,
encoding: None,
span,
});
}
fn key_val_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::KeyValSep,
encoding: None,
span,
});
}
fn scalar(&mut self, span: Span, encoding: Option<Encoding>, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::Scalar,
encoding,
span,
});
}
fn value_sep(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::ValueSep,
encoding: None,
span,
});
}
fn whitespace(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::Whitespace,
encoding: None,
span,
});
}
fn comment(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::Comment,
encoding: None,
span,
});
}
fn newline(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::Newline,
encoding: None,
span,
});
}
fn error(&mut self, span: Span, _error: &mut dyn ErrorSink) {
self.push(Event {
kind: EventKind::Error,
encoding: None,
span,
});
}
}
impl EventReceiver for () {}
/// Centralize validation for all whitespace-like content
pub struct ValidateWhitespace<'r, 's> {
receiver: &'r mut dyn EventReceiver,
source: Source<'s>,
}
impl<'r, 's> ValidateWhitespace<'r, 's> {
pub fn new(receiver: &'r mut dyn EventReceiver, source: Source<'s>) -> Self {
Self { receiver, source }
}
}
impl EventReceiver for ValidateWhitespace<'_, '_> {
fn std_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_open(span, error);
}
fn std_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_close(span, error);
}
fn array_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_open(span, error);
}
fn array_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_close(span, error);
}
fn inline_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
self.receiver.inline_table_open(span, error)
}
fn inline_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.inline_table_close(span, error);
}
fn array_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
self.receiver.array_open(span, error)
}
fn array_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_close(span, error);
}
fn simple_key(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.simple_key(span, encoding, error);
}
fn key_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_sep(span, error);
}
fn key_val_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_val_sep(span, error);
}
fn scalar(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.scalar(span, encoding, error);
}
fn value_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.value_sep(span, error);
}
fn whitespace(&mut self, span: Span, error: &mut dyn ErrorSink) {
#[cfg(feature = "unsafe")] // SAFETY: callers must use valid span
let raw = unsafe { self.source.get_unchecked(span) };
#[cfg(not(feature = "unsafe"))]
let raw = self.source.get(span).expect("token spans are valid");
raw.decode_whitespace(error);
self.receiver.whitespace(span, error);
}
fn comment(&mut self, span: Span, error: &mut dyn ErrorSink) {
#[cfg(feature = "unsafe")] // SAFETY: callers must use valid span
let raw = unsafe { self.source.get_unchecked(span) };
#[cfg(not(feature = "unsafe"))]
let raw = self.source.get(span).expect("token spans are valid");
raw.decode_comment(error);
self.receiver.comment(span, error);
}
fn newline(&mut self, span: Span, error: &mut dyn ErrorSink) {
#[cfg(feature = "unsafe")] // SAFETY: callers must use valid span
let raw = unsafe { self.source.get_unchecked(span) };
#[cfg(not(feature = "unsafe"))]
let raw = self.source.get(span).expect("token spans are valid");
raw.decode_newline(error);
self.receiver.newline(span, error);
}
fn error(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.error(span, error);
}
}
pub struct RecursionGuard<'r> {
receiver: &'r mut dyn EventReceiver,
max_depth: u32,
depth: i64,
}
impl<'r> RecursionGuard<'r> {
pub fn new(receiver: &'r mut dyn EventReceiver, max_depth: u32) -> Self {
Self {
receiver,
max_depth,
depth: 0,
}
}
fn within_depth(&self) -> bool {
self.depth <= self.max_depth as i64
}
}
impl EventReceiver for RecursionGuard<'_> {
fn std_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_open(span, error);
}
fn std_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.std_table_close(span, error);
}
fn array_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_open(span, error);
}
fn array_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.array_table_close(span, error);
}
fn inline_table_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
let allowed = self.receiver.inline_table_open(span, error);
self.depth += 1;
let within_depth = self.within_depth();
if allowed && !within_depth {
error.report_error(
ParseError::new("cannot recurse further; max recursion depth met")
.with_unexpected(span),
);
}
allowed && within_depth
}
fn inline_table_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.depth -= 1;
self.receiver.inline_table_close(span, error);
}
fn array_open(&mut self, span: Span, error: &mut dyn ErrorSink) -> bool {
let allowed = self.receiver.array_open(span, error);
self.depth += 1;
let within_depth = self.within_depth();
if allowed && !within_depth {
error.report_error(
ParseError::new("cannot recurse further; max recursion depth met")
.with_unexpected(span),
);
}
allowed && within_depth
}
fn array_close(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.depth -= 1;
self.receiver.array_close(span, error);
}
fn simple_key(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.simple_key(span, encoding, error);
}
fn key_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_sep(span, error);
}
fn key_val_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.key_val_sep(span, error);
}
fn scalar(&mut self, span: Span, encoding: Option<Encoding>, error: &mut dyn ErrorSink) {
self.receiver.scalar(span, encoding, error);
}
fn value_sep(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.value_sep(span, error);
}
fn whitespace(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.whitespace(span, error);
}
fn comment(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.comment(span, error);
}
fn newline(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.newline(span, error);
}
fn error(&mut self, span: Span, error: &mut dyn ErrorSink) {
self.receiver.error(span, error);
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Event {
kind: EventKind,
encoding: Option<Encoding>,
span: Span,
}
impl Event {
pub fn new_unchecked(kind: EventKind, encoding: Option<Encoding>, span: Span) -> Self {
Self {
kind,
encoding,
span,
}
}
#[inline(always)]
pub fn kind(&self) -> EventKind {
self.kind
}
#[inline(always)]
pub fn encoding(&self) -> Option<Encoding> {
self.encoding
}
#[inline(always)]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum EventKind {
StdTableOpen,
StdTableClose,
ArrayTableOpen,
ArrayTableClose,
InlineTableOpen,
InlineTableClose,
ArrayOpen,
ArrayClose,
SimpleKey,
KeySep,
KeyValSep,
Scalar,
ValueSep,
Whitespace,
Comment,
Newline,
Error,
}
impl EventKind {
pub const fn description(&self) -> &'static str {
match self {
Self::StdTableOpen => "std-table open",
Self::StdTableClose => "std-table close",
Self::ArrayTableOpen => "array-table open",
Self::ArrayTableClose => "array-table close",
Self::InlineTableOpen => "inline-table open",
Self::InlineTableClose => "inline-table close",
Self::ArrayOpen => "array open",
Self::ArrayClose => "array close",
Self::SimpleKey => "key",
Self::KeySep => "key separator",
Self::KeyValSep => "key-value separator",
Self::Scalar => "value",
Self::ValueSep => "value separator",
Self::Whitespace => "whitespace",
Self::Comment => "comment",
Self::Newline => "newline",
Self::Error => "error",
}
}
}

16
vendor/toml_parser/src/parser/mod.rs vendored Normal file
View File

@@ -0,0 +1,16 @@
//! A TOML push [parser][parse_document]
//!
//! This takes TOML [tokens][crate::lexer::Token] and [emits][EventReceiver] [events][Event].
mod document;
mod event;
pub use document::parse_document;
pub use document::parse_key;
pub use document::parse_simple_key;
pub use document::parse_value;
pub use event::Event;
pub use event::EventKind;
pub use event::EventReceiver;
pub use event::RecursionGuard;
pub use event::ValidateWhitespace;

394
vendor/toml_parser/src/source.rs vendored Normal file
View File

@@ -0,0 +1,394 @@
use crate::decoder::Encoding;
use crate::decoder::StringBuilder;
use crate::lexer::Lexer;
use crate::ErrorSink;
use crate::Expected;
/// Data encoded as TOML
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Source<'i> {
input: &'i str,
}
impl<'i> Source<'i> {
pub fn new(input: &'i str) -> Self {
Self { input }
}
/// Start lexing the TOML encoded data
pub fn lex(&self) -> Lexer<'i> {
Lexer::new(self.input)
}
/// Access the TOML encoded `&str`
pub fn input(&self) -> &'i str {
self.input
}
/// Return a subslice of the input
pub fn get(&self, span: impl SourceIndex) -> Option<Raw<'i>> {
span.get(self)
}
/// Return an unchecked subslice of the input
///
/// ## Safety
///
/// Callers of this function are responsible that these preconditions are satisfied:
/// - The starting index must not exceed the ending index;
/// - Indexes must be within bounds of the original slice;
/// - Indexes must lie on UTF-8 sequence boundaries.
///
/// Or one of:
/// - `span` came from [`Source::lex`]
///
/// Failing any of those, the returned string slice may reference invalid memory or violate the invariants communicated by `str` type.
#[cfg(feature = "unsafe")]
pub unsafe fn get_unchecked(&self, span: impl SourceIndex) -> Raw<'i> {
// SAFETY: Same safety guarantees are required
unsafe { span.get_unchecked(self) }
}
/// Return a subslice of the input
fn get_raw_str(&self, span: Span) -> Option<&'i str> {
let index = span.start()..span.end();
self.input.get(index)
}
/// Return an unchecked subslice of the input
///
/// ## Safety
///
/// Callers of this function are responsible that these preconditions are satisfied:
/// - The starting index must not exceed the ending index;
/// - Indexes must be within bounds of the original slice;
/// - Indexes must lie on UTF-8 sequence boundaries.
///
/// Or one of:
/// - `span` came from [`Source::lex`]
///
/// Failing any of those, the returned string slice may reference invalid memory or violate the invariants communicated by `str` type.
#[cfg(feature = "unsafe")]
unsafe fn get_raw_str_unchecked(&self, span: Span) -> &'i str {
let index = span.start()..span.end();
// SAFETY: Same safety guarantees are required
unsafe { self.input.get_unchecked(index) }
}
}
/// A slice of [`Source`]
#[derive(Copy, Clone, Debug)]
pub struct Raw<'i> {
raw: &'i str,
encoding: Option<Encoding>,
span: Span,
}
impl<'i> Raw<'i> {
pub fn new_unchecked(raw: &'i str, encoding: Option<Encoding>, span: Span) -> Self {
Self {
raw,
encoding,
span,
}
}
pub fn decode_key(&self, output: &mut dyn StringBuilder<'i>, error: &mut dyn ErrorSink) {
let mut error = |err: crate::ParseError| {
error.report_error(err.rebase_spans(self.span.start));
};
match self.encoding {
Some(Encoding::LiteralString) => {
crate::decoder::string::decode_literal_string(*self, output, &mut error);
}
Some(Encoding::BasicString) => {
crate::decoder::string::decode_basic_string(*self, output, &mut error);
}
Some(Encoding::MlLiteralString) => {
error.report_error(
crate::ParseError::new("keys cannot be multi-line literal strings")
.with_expected(&[
Expected::Description("basic string"),
Expected::Description("literal string"),
])
.with_unexpected(Span::new_unchecked(0, self.len())),
);
crate::decoder::string::decode_ml_literal_string(*self, output, &mut error);
}
Some(Encoding::MlBasicString) => {
error.report_error(
crate::ParseError::new("keys cannot be multi-line basic strings")
.with_expected(&[
Expected::Description("basic string"),
Expected::Description("literal string"),
])
.with_unexpected(Span::new_unchecked(0, self.len())),
);
crate::decoder::string::decode_ml_basic_string(*self, output, &mut error);
}
None => crate::decoder::string::decode_unquoted_key(*self, output, &mut error),
}
}
#[must_use]
pub fn decode_scalar(
&self,
output: &mut dyn StringBuilder<'i>,
error: &mut dyn ErrorSink,
) -> crate::decoder::scalar::ScalarKind {
let mut error = |err: crate::ParseError| {
error.report_error(err.rebase_spans(self.span.start));
};
match self.encoding {
Some(Encoding::LiteralString) => {
crate::decoder::string::decode_literal_string(*self, output, &mut error);
crate::decoder::scalar::ScalarKind::String
}
Some(Encoding::BasicString) => {
crate::decoder::string::decode_basic_string(*self, output, &mut error);
crate::decoder::scalar::ScalarKind::String
}
Some(Encoding::MlLiteralString) => {
crate::decoder::string::decode_ml_literal_string(*self, output, &mut error);
crate::decoder::scalar::ScalarKind::String
}
Some(Encoding::MlBasicString) => {
crate::decoder::string::decode_ml_basic_string(*self, output, &mut error);
crate::decoder::scalar::ScalarKind::String
}
None => crate::decoder::scalar::decode_unquoted_scalar(*self, output, &mut error),
}
}
pub fn decode_whitespace(&self, _error: &mut dyn ErrorSink) {
// whitespace is always valid
}
pub fn decode_comment(&self, error: &mut dyn ErrorSink) {
let mut error = |err: crate::ParseError| {
error.report_error(err.rebase_spans(self.span.start));
};
crate::decoder::ws::decode_comment(*self, &mut error);
}
pub fn decode_newline(&self, error: &mut dyn ErrorSink) {
let mut error = |err: crate::ParseError| {
error.report_error(err.rebase_spans(self.span.start));
};
crate::decoder::ws::decode_newline(*self, &mut error);
}
pub fn as_str(&self) -> &'i str {
self.raw
}
pub fn as_bytes(&self) -> &'i [u8] {
self.raw.as_bytes()
}
pub fn len(&self) -> usize {
self.raw.len()
}
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}
}
/// Location within the [`Source`]
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Span {
start: usize,
end: usize,
}
impl Span {
pub fn new_unchecked(start: usize, end: usize) -> Self {
Self { start, end }
}
pub fn is_empty(&self) -> bool {
self.end <= self.start
}
pub fn len(&self) -> usize {
self.end - self.start
}
pub fn start(&self) -> usize {
self.start
}
pub fn end(&self) -> usize {
self.end
}
pub fn before(&self) -> Self {
Self::new_unchecked(self.start, self.start)
}
pub fn after(&self) -> Self {
Self::new_unchecked(self.end, self.end)
}
/// Extend this `Raw` to the end of `after`
#[must_use]
pub fn append(&self, after: Self) -> Self {
Self::new_unchecked(self.start, after.end)
}
}
impl core::fmt::Debug for Span {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
(self.start..self.end).fmt(f)
}
}
impl core::ops::Add<usize> for Span {
type Output = Self;
fn add(self, offset: usize) -> Self::Output {
Self::Output {
start: self.start + offset,
end: self.end + offset,
}
}
}
impl core::ops::Add<Span> for usize {
type Output = Span;
fn add(self, span: Span) -> Self::Output {
Self::Output {
start: span.start + self,
end: span.end + self,
}
}
}
impl core::ops::AddAssign<usize> for Span {
fn add_assign(&mut self, rhs: usize) {
self.start += rhs;
self.end += rhs;
}
}
/// A helper trait used for indexing operations on [`Source`]
pub trait SourceIndex: sealed::Sealed {
/// Return a subslice of the input
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>>;
/// Return an unchecked subslice of the input
///
/// ## Safety
///
/// Callers of this function are responsible that these preconditions are satisfied:
/// - The starting index must not exceed the ending index;
/// - Indexes must be within bounds of the original slice;
/// - Indexes must lie on UTF-8 sequence boundaries.
///
/// Or one of:
/// - `span` came from [`Source::lex`]
///
/// Failing any of those, the returned string slice may reference invalid memory or violate the invariants communicated by `str` type.
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i>;
}
impl SourceIndex for Span {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
(&self).get(source)
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
// SAFETY: Same safety guarantees are required
unsafe { (&self).get_unchecked(source) }
}
}
impl SourceIndex for &Span {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
let encoding = None;
source
.get_raw_str(*self)
.map(|s| Raw::new_unchecked(s, encoding, *self))
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
let encoding = None;
// SAFETY: Same safety guarantees are required
let raw = unsafe { source.get_raw_str_unchecked(*self) };
Raw::new_unchecked(raw, encoding, *self)
}
}
impl SourceIndex for crate::lexer::Token {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
(&self).get(source)
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
// SAFETY: Same safety guarantees are required
unsafe { (&self).get_unchecked(source) }
}
}
impl SourceIndex for &crate::lexer::Token {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
let encoding = self.kind().encoding();
source
.get_raw_str(self.span())
.map(|s| Raw::new_unchecked(s, encoding, self.span()))
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
let encoding = self.kind().encoding();
// SAFETY: Same safety guarantees are required
let raw = unsafe { source.get_raw_str_unchecked(self.span()) };
Raw::new_unchecked(raw, encoding, self.span())
}
}
impl SourceIndex for crate::parser::Event {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
(&self).get(source)
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
// SAFETY: Same safety guarantees are required
unsafe { (&self).get_unchecked(source) }
}
}
impl SourceIndex for &crate::parser::Event {
fn get<'i>(self, source: &Source<'i>) -> Option<Raw<'i>> {
let encoding = self.encoding();
source
.get_raw_str(self.span())
.map(|s| Raw::new_unchecked(s, encoding, self.span()))
}
#[cfg(feature = "unsafe")]
unsafe fn get_unchecked<'i>(self, source: &Source<'i>) -> Raw<'i> {
let encoding = self.encoding();
// SAFETY: Same safety guarantees are required
let raw = unsafe { source.get_raw_str_unchecked(self.span()) };
Raw::new_unchecked(raw, encoding, self.span())
}
}
mod sealed {
pub trait Sealed {}
impl Sealed for crate::Span {}
impl Sealed for &crate::Span {}
impl Sealed for crate::lexer::Token {}
impl Sealed for &crate::lexer::Token {}
impl Sealed for crate::parser::Event {}
impl Sealed for &crate::parser::Event {}
}