Skip to content

Commit

Permalink
feature branch merge
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Dec 3, 2024
2 parents fb7c92b + 660013e commit a054d9b
Show file tree
Hide file tree
Showing 28 changed files with 549 additions and 156 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ rust-version = "1.56.0"
edition = "2021"

[features]
default = ["span"]
default = ["span", "serde"]
span = []

[dependencies]
miette = "7.2.0"
num = "0.4.2"
serde = { version = "1.0.210", optional = true }
thiserror = "1.0.40"
winnow = { version = "0.6.20", features = ["alloc", "unstable-recover"] }

Expand Down
235 changes: 235 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
use serde::{de, Deserialize};
use thiserror::Error;
use winnow::{stream::Recoverable, Located};

use crate::{v2_parser::KdlParseError, KdlParseFailure};

/// serde deserializer for KDL documents
#[derive(Debug)]
pub struct Deserializer<'de> {
input: Recoverable<Located<&'de str>, KdlParseError>,
}

impl<'de> Deserializer<'de> {
/// Create a new deserializer from a string
pub fn from_str(input: &'de str) -> Self {
Self {
input: Recoverable::new(Located::new(input)),
}
}
}

/// Deserialize a type from a KDL string
pub fn from_str<'a, T>(input: &'a str) -> Result<T, KdlParseFailure>
where
T: Deserialize<'a>,
{
}

#[derive(Debug, Error)]
struct DeError(String);

impl std::fmt::Display for DeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl de::Error for DeError {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
DeError(msg.to_string())
}
}

struct KdlVisitor;

impl<'de> de::Visitor<'de> for KdlVisitor {
type Value = ();

fn expecting<'a>(&self, formatter: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
write!(formatter, "a KDL value")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
while let Some(key) = map.next_key()? {
match key {
"type" => {
let value = map.next_value::<String>()?;
println!("type: {}", value);
}
"value" => {
let value = map.next_value::<String>()?;
println!("value: {}", value);
}
_ => {
map.next_value::<serde::de::IgnoredAny>()?;
}
}
}

Ok(())
}
}

impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = DeError;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.deserialize_map(visitor)
}

fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_unit_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_enum<V>(
self,
name: &'static str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}

fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
todo!()
}
}
25 changes: 13 additions & 12 deletions src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ second_node /* This time, the comment is here */ param=153 {
/- comment
/* block comment */
inline /*comment*/ here
another /-commend there
another /-comment there
after some whitespace
Expand Down Expand Up @@ -485,7 +485,7 @@ final;";
);

let foo = doc.get("foo").expect("expected a foo node");
assert_eq!(foo.format().map(|f| &f.trailing[..]), Some("\n"));
assert_eq!(foo.format().map(|f| &f.terminator[..]), Some("\n"));
assert_eq!(&foo[2], &"three".into());
assert_eq!(&foo["bar"], &"baz".into());
assert_eq!(
Expand Down Expand Up @@ -527,6 +527,7 @@ final;";
// if you're making KdlEntries this way, you need to inject
// your own whitespace (or format the node)
node.push(" \"blah\"=0xDEADbeef".parse::<KdlEntry>()?);
dbg!(&node);
doc.nodes_mut().push(node);

assert_eq!(
Expand Down Expand Up @@ -714,7 +715,8 @@ this {
}
// that's
nice
inline { time; to; live "our" "dreams"; "y;all"; }
inline { time; to; live "our" "dreams"; "y;all" }
"####;

let doc: KdlDocument = input.parse()?;
Expand All @@ -724,8 +726,9 @@ inline { time; to; live "our" "dreams"; "y;all"; }

// Now check some more interesting concrete spans

// The whole document should presumably be "the input" again?
check_span(input, doc.span(), &input);
// The whole document should be everything from the first node until the
// last before_terminator whitespace.
check_span(&input[1..(input.len() - 2)], doc.span(), &input);

// This one-liner node should be the whole line without leading whitespace
let is_node = doc
Expand Down Expand Up @@ -772,13 +775,11 @@ inline { time; to; live "our" "dreams"; "y;all"; }
);

// The child document is a little weird, it's the contents *inside* the braces
// with extra newlines on both ends.
// without the surrounding whitespace/comments. Just the actual contents.
check_span(
r####"{
"it" /*shh*/ "has"="💯" ##"the"##
r####""it" /*shh*/ "has"="💯" ##"the"##
Best🎊est
"syntax ever"
}"####,
"syntax ever""####,
and_node.children().unwrap().span(),
&input,
);
Expand Down Expand Up @@ -807,14 +808,14 @@ inline { time; to; live "our" "dreams"; "y;all"; }
// Make sure inline nodes work ok
let inline_node = doc.get("inline").unwrap();
check_span(
r#"inline { time; to; live "our" "dreams"; "y;all"; }"#,
r#"inline { time; to; live "our" "dreams"; "y;all" }"#,
inline_node.span(),
&input,
);

let inline_children = inline_node.children().unwrap();
check_span(
r#"{ time; to; live "our" "dreams"; "y;all"; }"#,
r#"time; to; live "our" "dreams"; "y;all" "#,
inline_children.span(),
&input,
);
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,8 @@ mod node;
mod value;

mod v2_parser;

#[cfg(feature = "serde")]
pub mod de;
#[cfg(feature = "serde")]
pub mod se;
Loading

0 comments on commit a054d9b

Please sign in to comment.