Skip to main content

StreamParser

Struct StreamParser 

Source
pub struct StreamParser<T: StreamReference = String> { /* private fields */ }
Expand description

Incrementally emits complete top-level Links Notation records.

A record can acquire indented children, so a terminating newline is not by itself a safe boundary. A record is committed when the next non-indented content line begins, and the canonical parser validates every committed segment. Set collection off for bounded-memory callback or iterator use.

StreamParser::new() emits LiNo<String>, like parse_lino_to_links. StreamParser::syntax emits LiNo<SyntaxReference>, like parse_lino_to_syntax_links, so every link remembers how its ID was written:

use links_notation::StreamParser;

let mut stream = StreamParser::syntax();
stream.write("(t 1 '1')\n").unwrap();
let links = stream.finish().unwrap();
assert_eq!(links[0].to_string(), "(t 1 1)");
let links_notation::LiNo::Link { values, .. } = &links[0] else { unreachable!() };
assert_eq!(values[2].raw_id(), Some("'1'"));
assert_eq!(values[2].quote(), Some('\''));

Implementations§

Source§

impl StreamParser

Source

pub fn new() -> Self

Create a parser with the canonical default options.

Examples found in repository?
examples/streaming_parser.rs (line 15)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source

pub fn with_config(config: ParserConfig) -> Self

Create a parser with explicit canonical parser options.

Source

pub fn parse_chunks<I, S>(chunks: I) -> StreamIterator<I::IntoIter> ⓘ
where I: IntoIterator<Item = S>, S: AsRef<str>,

Lazily parse any iterator of string-like chunks.

Examples found in repository?
examples/streaming_parser.rs (line 31)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source§

impl StreamParser<SyntaxReference>

Source

pub fn syntax() -> Self

Create a parser whose links record how each ID was written.

Source

pub fn syntax_with_config(config: ParserConfig) -> Self

Create a parser with explicit options whose links record how each ID was written.

Source

pub fn parse_syntax_chunks<I, S>( chunks: I, ) -> StreamIterator<I::IntoIter, SyntaxReference> ⓘ
where I: IntoIterator<Item = S>, S: AsRef<str>,

Lazily parse any iterator of string-like chunks into links that record how each ID was written.

Source§

impl<T: StreamReference> StreamParser<T>

Register a callback invoked once for every completed link.

Examples found in repository?
examples/streaming_parser.rs (lines 16-19)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source

pub fn on_error<F>(&mut self, callback: F) -> &mut Self
where F: FnMut(&StreamParseError) + Send + 'static,

Register a callback invoked when parsing fails.

Source

pub fn set_collect(&mut self, collect: bool) -> &mut Self

Enable or disable retaining links for finish and drain.

Examples found in repository?
examples/streaming_parser.rs (line 16)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source

pub fn set_max_buffer_size( &mut self, max_buffer_size: usize, ) -> Result<&mut Self, StreamParseError>

Set the largest unresolved record accepted by the stream.

Source

pub fn write(&mut self, chunk: &str) -> Result<Vec<LiNo<T>>, StreamParseError>

Consume a string chunk and return links made complete by it.

Examples found in repository?
examples/streaming_parser.rs (line 24)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source

pub fn finish(&mut self) -> Result<Vec<LiNo<T>>, StreamParseError>

Finish the stream and return all undrained or newly emitted links.

Examples found in repository?
examples/streaming_parser.rs (line 26)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let document = "first loves data\nprofile:\n  name Ada\nlast sees first";
11
12    // Disabling collection retains only the unresolved top-level record.
13    let count = Arc::new(AtomicUsize::new(0));
14    let callback_count = Arc::clone(&count);
15    let mut stream = StreamParser::new();
16    stream.set_collect(false).on_link(move |link| {
17        callback_count.fetch_add(1, Ordering::Relaxed);
18        println!("callback: {link}");
19    });
20
21    // Chunk boundaries are arbitrary: this writes one Unicode scalar at a time.
22    let mut encoded = [0; 4];
23    for symbol in document.chars() {
24        stream.write(symbol.encode_utf8(&mut encoded))?;
25    }
26    stream.finish()?;
27    println!("parsed {} links", count.load(Ordering::Relaxed));
28
29    // Iteration is lazy and automatically disables collection.
30    let chunks = ["one link\npro", "file:\n  name Ada\n", "two link"];
31    for link in StreamParser::parse_chunks(chunks) {
32        println!("iterator: {}", link?);
33    }
34
35    Ok(())
36}
Source

pub fn drain(&mut self) -> Vec<LiNo<T>>

Return and forget retained links.

Source

pub fn reset(&mut self) -> &mut Self

Reuse this parser while preserving its configuration and callbacks.

Source

pub fn position(&self) -> StreamPosition

Return the absolute stream position and unresolved buffer size.

Trait Implementations§

Source§

impl Default for StreamParser

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T = String> !RefUnwindSafe for StreamParser<T>

§

impl<T = String> !Sync for StreamParser<T>

§

impl<T = String> !UnwindSafe for StreamParser<T>

§

impl<T> Forget for StreamParser<T>

§

impl<T> Freeze for StreamParser<T>
where Option<Box<dyn FnMut(&LiNo<T>) + Send>>: Freeze, Vec<LiNo<T>>: Freeze,

§

impl<T> Send for StreamParser<T>
where Option<Box<dyn FnMut(&LiNo<T>) + Send>>: Send, Vec<LiNo<T>>: Send,

§

impl<T> Unpin for StreamParser<T>
where Option<Box<dyn FnMut(&LiNo<T>) + Send>>: Unpin, Vec<LiNo<T>>: Unpin,

§

impl<T> UnsafeUnpin for StreamParser<T>
where Option<Box<dyn FnMut(&LiNo<T>) + Send>>: UnsafeUnpin, Vec<LiNo<T>>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.