diff options
| author | 2024-03-04 16:14:28 +0000 | |
|---|---|---|
| committer | 2024-03-04 16:14:28 +0000 | |
| commit | 844f3a5d11e4360e9d6bdb79cfed49287aa8b14d (patch) | |
| tree | 5525c4f134ef3d7a6082935baa61e6097670c968 /src | |
| download | peanuts-844f3a5d11e4360e9d6bdb79cfed49287aa8b14d.tar.gz peanuts-844f3a5d11e4360e9d6bdb79cfed49287aa8b14d.tar.bz2 peanuts-844f3a5d11e4360e9d6bdb79cfed49287aa8b14d.zip | |
initial commit
Diffstat (limited to '')
| -rw-r--r-- | src/element.rs | 55 | ||||
| -rw-r--r-- | src/error.rs | 1 | ||||
| -rw-r--r-- | src/event.rs | 1 | ||||
| -rw-r--r-- | src/lexer.rs | 9 | ||||
| -rw-r--r-- | src/lib.rs | 15 | ||||
| -rw-r--r-- | src/parser.rs | 1 | ||||
| -rw-r--r-- | src/reader.rs | 32 | ||||
| -rw-r--r-- | src/writer.rs | 47 | 
8 files changed, 161 insertions, 0 deletions
| diff --git a/src/element.rs b/src/element.rs new file mode 100644 index 0000000..3273ba0 --- /dev/null +++ b/src/element.rs @@ -0,0 +1,55 @@ +// elements resemble a final tree, including inherited namespace information + +use std::collections::HashMap; + +// when are namespaces names chosen then if they are automatically calculated +// namespaces are held by readers and writers. +pub struct Namespace { +    prefix: Option<String>, +    namespace: String, +} + +// names are qualified, they contain the namespace +pub struct Name { +    namespace: String, +    name: String, +} + +pub enum Node { +    Element(Element), +    Text(String), +} + +// should this be a trait? +pub struct Element { +    name: Name, +    // namespace: (Name, String), // can't have this, must be external method that is called within the context of a reader/writer +    // each element once created contains the qualified namespace information for that element +    // the name contains the qualified namespace so this is unnecessary +    // namespace: String, +    // hashmap of explicit namespace declarations on the element itself only +    // possibly not needed as can be calculated at write time depending on context and qualified namespace, and for reading, element validity and namespaces are kept track of by the reader. +    // namespaces: HashMap<Option<String>, String>, +    // attributes can be in a different namespace than the element. how to make sure they are valid? +    // maybe include the namespace instead of or with the prefix +    // you can calculate the prefix from the namespaced name and the current writer context +    // you can validate the prefix and calculate the namespace from the current reader context +    // this results in readers and writers being able to return qualification errors as they aren't able to create elements until every part is qualified. +    attributes: HashMap<Name, String>, +    children: Option<Vec<Node>>, +} + +// example of deriving an element: + +// #[derive(XMLWrite, XMLRead)] +// #[peanuts(namespace = "jabber:client", namespace:stream = "http://etherx.jabber.org/streams", name = "stream:stream")] +// pub struct Stream { +//     from: JID, +//     id: String, +//     to: JID, +//     version: String, +//     #[peanuts(namespace = "http://www.w3.org/XML/1998/namespace")] +//     lang: Lang, +// } + +// note: if an element name has a prefix all unprefixed attributes are qualified by the namespace of the prefix, so in this example from's Name's namespace would be "http://etherx.jabber.org/streams" diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..12fcaf2 --- /dev/null +++ b/src/error.rs @@ -0,0 +1 @@ +pub enum Error {} diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..1eab55b --- /dev/null +++ b/src/event.rs @@ -0,0 +1 @@ +// tags, declaration, comments, text. individual bits and what they contain, e.g. tag contains attributes and namespace declarations, lang, ONLY within the tag diff --git a/src/lexer.rs b/src/lexer.rs new file mode 100644 index 0000000..abb5ebd --- /dev/null +++ b/src/lexer.rs @@ -0,0 +1,9 @@ +// lexer: tokenizes to bits like '<', '<?', '"', etc. + +pub enum Token { +    Whitespace, +    OpenTag, +    CloseTag, +    Slash, +    Text(String), +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5d1046f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,15 @@ +mod element; +mod error; +mod reader; +mod writer; + +#[cfg(test)] +mod tests { +    use super::*; + +    #[test] +    fn it_works() { +        let result = 2 + 2; +        assert_eq!(result, 4); +    } +} diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..b2a8579 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1 @@ +// parser: parses tokens from lexer into events diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..05afc73 --- /dev/null +++ b/src/reader.rs @@ -0,0 +1,32 @@ +use futures::Stream; +use tokio::io::AsyncRead; + +use crate::{ +    element::{Element, Name, Namespace}, +    error::Error, +}; + +/// streaming reader that tracks depth and available namespaces at current depth +pub struct Reader<R> { +    stream: R, +    // holds which tags we are in atm over depth +    depth: Vec<Name>, +    namespaces: Vec<(usize, Namespace)>, +} + +impl<R: AsyncRead> Reader<R> { +    pub async fn read(&self) -> Result<impl From<Element>, Error> {} +    pub async fn read_start(&self) -> Result<impl From<Element>, Error> {} +    pub async fn read_end(&self) -> Result<(), Error> {} +} + +impl<R: AsyncRead> Stream for Reader<R> { +    type Item = impl From<Element>; + +    async fn poll_next( +        self: std::pin::Pin<&mut Self>, +        cx: &mut std::task::Context<'_>, +    ) -> std::task::Poll<Option<Self::Item>> { +        todo!() +    } +} diff --git a/src/writer.rs b/src/writer.rs new file mode 100644 index 0000000..d7fc037 --- /dev/null +++ b/src/writer.rs @@ -0,0 +1,47 @@ +use futures::{AsyncWrite, Sink}; + +use crate::{ +    element::{Element, Name, Namespace}, +    error::Error, +}; + +pub struct Writer<W> { +    stream: W, +    depth: Vec<Name>, +    namespaces: Vec<(usize, Namespace)>, +} + +impl<W: AsyncWrite> Writer<W> { +    pub async fn write(&self, element: impl Into<Element>) -> Result<(), Error> {} +    pub async fn write_start(&self, element: impl Into<Element>) -> Result<(), Error> {} +    pub async fn write_end(&self) -> Result<(), Error> {} +} + +impl<W: AsyncWrite, E: Into<Element>> Sink<E> for Writer<W> { +    type Error = Error; + +    fn poll_ready( +        self: std::pin::Pin<&mut Self>, +        cx: &mut std::task::Context<'_>, +    ) -> std::task::Poll<Result<(), Self::Error>> { +        todo!() +    } + +    fn start_send(self: std::pin::Pin<&mut Self>, item: E) -> Result<(), Self::Error> { +        todo!() +    } + +    fn poll_flush( +        self: std::pin::Pin<&mut Self>, +        cx: &mut std::task::Context<'_>, +    ) -> std::task::Poll<Result<(), Self::Error>> { +        todo!() +    } + +    fn poll_close( +        self: std::pin::Pin<&mut Self>, +        cx: &mut std::task::Context<'_>, +    ) -> std::task::Poll<Result<(), Self::Error>> { +        todo!() +    } +} | 
