#[derive(Debug, Clone, PartialEq)]
pub struct KdlDocument {
pub(crate) nodes: Vec<KdlNode>,
}
impl KdlDocument {
pub fn nodes(&self) -> &[KdlNode] {
&self.nodes
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct KdlNode {
pub(crate) ty: Option<String>,
pub(crate) name: String,
pub(crate) entries: Vec<KdlEntry>,
pub(crate) children: Option<Vec<KdlNode>>,
}
impl KdlNode {
pub fn ty(&self) -> Option<&str> {
self.ty.as_deref()
}
pub fn name(&self) -> &str {
&self.name
}
pub fn entries(&self) -> &[KdlEntry] {
&self.entries
}
pub fn children(&self) -> Option<&[KdlNode]> {
self.children.as_deref()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum KdlEntry {
Argument {
ty: Option<String>,
value: KdlValue,
},
Property {
key: String,
ty: Option<String>,
value: KdlValue,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum KdlValue {
String(String),
Number(KdlNumber),
Bool(bool),
Null,
}
#[derive(Debug, Clone)]
pub struct KdlNumber {
pub(crate) raw: String,
pub(crate) as_i64: Option<i64>,
pub(crate) as_f64: Option<f64>,
}
impl KdlNumber {
pub fn raw(&self) -> &str {
&self.raw
}
pub fn as_i64(&self) -> Option<i64> {
self.as_i64
}
pub fn as_f64(&self) -> Option<f64> {
self.as_f64
}
}
impl PartialEq for KdlNumber {
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct KdlError {
pub(crate) line: usize,
pub(crate) col: usize,
pub(crate) kind: KdlErrorKind,
}
impl KdlError {
pub fn line(&self) -> usize {
self.line
}
pub fn col(&self) -> usize {
self.col
}
pub fn kind(&self) -> &KdlErrorKind {
&self.kind
}
}
impl core::fmt::Display for KdlError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}:{}: {}", self.line, self.col, self.kind)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum KdlErrorKind {
UnexpectedChar(char),
UnexpectedEof,
InvalidEscape,
InvalidUnicodeEscape,
InvalidNumber,
DisallowedCodePoint(char),
BareKeyword,
UnmatchedBlockCommentEnd,
UnclosedBlockComment,
UnclosedString,
InconsistentIndentation,
InvalidSlashdash,
}
impl core::fmt::Display for KdlErrorKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::UnexpectedChar(c) => write!(f, "unexpected character: {:?}", c),
Self::UnexpectedEof => write!(f, "unexpected end of input"),
Self::InvalidEscape => write!(f, "invalid escape sequence"),
Self::InvalidUnicodeEscape => write!(f, "invalid unicode escape"),
Self::InvalidNumber => write!(f, "invalid number literal"),
Self::DisallowedCodePoint(c) => {
write!(f, "disallowed code point: U+{:04X}", *c as u32)
}
Self::BareKeyword => write!(f, "bare keyword (use #true, #false, #null, etc.)"),
Self::UnmatchedBlockCommentEnd => write!(f, "unmatched */"),
Self::UnclosedBlockComment => write!(f, "unclosed block comment"),
Self::UnclosedString => write!(f, "unclosed string"),
Self::InconsistentIndentation => write!(f, "inconsistent multiline string indentation"),
Self::InvalidSlashdash => write!(f, "slashdash in invalid position"),
}
}
}