initial
This commit is contained in:
commit
99921e9f2a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "charon"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"streaming-iterator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "streaming-iterator"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "charon"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
streaming-iterator = "0.1.9"
|
49
src/lib.rs
Normal file
49
src/lib.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#![feature(bufread_skip_until)]
|
||||||
|
mod tokenizer;
|
||||||
|
mod reader;
|
||||||
|
|
||||||
|
use std::io::{BufRead, BufReader, Read};
|
||||||
|
|
||||||
|
pub struct Attribute<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub value: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
//impl<'a> Attribute<'a> {
|
||||||
|
// pub fn new(&[u8]) -> Self {
|
||||||
|
// Self {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
pub struct Element<'a> {
|
||||||
|
pub tag: &'a str,
|
||||||
|
attributes: Vec<Attribute<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Node<'a> {
|
||||||
|
Text(&'a [u8]),
|
||||||
|
Tag(&'a Element<'a>),
|
||||||
|
EndTag(&'a Element<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Charon<R> {
|
||||||
|
reader: BufReader<R>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R> Charon<R> {
|
||||||
|
pub fn new(reader: BufReader<R>) -> Self {
|
||||||
|
Self { reader }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read> Charon<R> {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn reader() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
82
src/reader.rs
Normal file
82
src/reader.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use std::io::{Read, BufRead};
|
||||||
|
|
||||||
|
pub trait Peek {
|
||||||
|
type Item;
|
||||||
|
fn peek(&mut self) -> Option<&Self::Item> {
|
||||||
|
self.peek_n(1)?.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek_n(&mut self, n: usize) -> Option<&[Self::Item]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Reader<R> {
|
||||||
|
inner: R
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R> Reader<R> {
|
||||||
|
pub fn new(inner: R) -> Self {
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: BufRead> Peek for Reader<R> {
|
||||||
|
type Item = u8;
|
||||||
|
|
||||||
|
fn peek_n(&mut self, n: usize) -> Option<&[Self::Item]> {
|
||||||
|
Some(&self.fill_buf().ok()?[..n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read> Iterator for Reader<R> {
|
||||||
|
type Item = u8;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut buf = [0u8];
|
||||||
|
self.inner.read(&mut buf).ok()?;
|
||||||
|
Some(buf[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read> Read for Reader<R> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
self.inner.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: BufRead> BufRead for Reader<R> {
|
||||||
|
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
|
||||||
|
self.inner.fill_buf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.inner.consume(amt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
|
use crate::reader::Peek;
|
||||||
|
|
||||||
|
use super::Reader;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_read() {
|
||||||
|
let mut reader = Reader::new(BufReader::new(b"this is a test string".as_slice()));
|
||||||
|
assert_eq!(Some(b't'), reader.next());
|
||||||
|
assert_eq!(Some(b'h'), reader.next());
|
||||||
|
assert_eq!(Some(b'i'), reader.next());
|
||||||
|
assert_eq!(Some(b's'), reader.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_peek() {
|
||||||
|
let mut reader = Reader::new(BufReader::new(b"this is a test string".as_slice()));
|
||||||
|
assert_eq!(Some(&b't'), reader.peek());
|
||||||
|
assert_eq!(Some(&b't'), reader.peek());
|
||||||
|
assert_eq!("this", String::from_utf8_lossy(reader.peek_n(4).unwrap()));
|
||||||
|
assert_eq!("this", String::from_utf8_lossy(reader.peek_n(4).unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
22
src/tokenizer.rs
Normal file
22
src/tokenizer.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
pub enum Token<'a> {
|
||||||
|
Space,
|
||||||
|
TagOpen,
|
||||||
|
TagClose,
|
||||||
|
QuoteOpen,
|
||||||
|
QuoteClose,
|
||||||
|
Equals,
|
||||||
|
Tag(&'a str),
|
||||||
|
Attribute(&'a str),
|
||||||
|
Value(&'a str)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Tokenizer;
|
||||||
|
|
||||||
|
impl Tokenizer {
|
||||||
|
pub fn parse<R: Read>(reader: R) -> Vec<Token> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue