Skip to main content

Streamer

Struct Streamer 

Source
pub struct Streamer { /* private fields */ }
Expand description

Streaming converter.

Feed it chunks and it returns only as much as is safe to emit right now. Markup caught on a boundary (cut off at **굵) stays inside until the next chunk arrives. This is the core of the library — converting a finished document is a problem others have already solved, while the boundary problem shows up on every channel as long as you stream.

§Example

use mdwire::{Channel, Streamer};

let mut s = Streamer::new(Channel::TelegramHtml);
let mut out = String::new();
// A chunk boundary inside `**` never sends half a marker.
out.push_str(s.push("앞말 **굵"));
out.push_str(s.push("게** 뒷말"));
out.push_str(s.finish());
assert_eq!(out, "앞말 <b>굵게</b> 뒷말");

Implementations§

Source§

impl Streamer

Source

pub fn new(channel: Channel) -> Self

Source

pub fn with_options(channel: Channel, options: Options) -> Self

Builds one with options.

Source

pub fn repairs(&self) -> Repairs

What normalization has repaired so far. After finish, it covers the whole document.

Source

pub fn push(&mut self, chunk: &str) -> &str

Pushes a chunk and returns the output that can be emitted now.

The returned slice is valid only until the next call. To avoid allocation entirely, use Streamer::push_into — both call the same code (SPEC.md section 5).

Source

pub fn push_into(&mut self, chunk: &str, out: &mut String)

Writes directly into the caller’s buffer. The canonical signature — zero allocations per chunk.

Source

pub fn finish(&mut self) -> &str

Signals the end of input. Emits everything left (open markup is closed).

Source

pub fn finish_into(&mut self, out: &mut String)

The allocation-free version of Streamer::finish.

Source

pub fn preview(&mut self) -> &str

The tail that would follow the final output if input ended now. Appending it to the accumulated output gives a shape that can be sent on the spot — it goes where Streamer::close_open goes, but also renders what is being held back: open emphasis closed (**굵 → <b>굵</b>), tables with the rows received so far, code spans closed. It is the default for callers that redraw the whole accumulated output (React, Telegram editMessageText, Slack chat.update).

The tail takes the same finish path as batch rendering, so its syntax is always valid. But it is a guess — later chunks can change the shape, for example a code span that never closes turns back into text. After finishing, Streamer::revised tells you whether the result differs from the last preview. Do not put it into the accumulated output itself.

The cost is proportional to the size of the currently open block (the engine is cloned). Call it when drawing the screen, not on every chunk.

use mdwire::{Channel, Streamer};

let mut s = Streamer::new(Channel::TelegramHtml);
let mut acc = String::new();
s.push_into("앞말 **굵", &mut acc);
assert_eq!(acc, "앞말 ");                       // final output so far
assert_eq!(format!("{acc}{}", s.preview()), "앞말 <b>굵</b>");

s.push_into("게** 끝", &mut acc);
let last = format!("{acc}{}", s.preview());
s.finish_into(&mut acc);
assert_eq!(acc, last);
assert!(!s.revised());                          // the last frame is already the result
Source

pub fn preview_into(&mut self, out: &mut String)

Appends Streamer::preview to the caller’s buffer.

Source

pub fn revised(&self) -> bool

Whether the final output differs from the last preview — check it after finish. If false, the last screen drawn (accumulated output + preview) already is the final output, so no redraw is needed. Telegram returns 400 (“message is not modified”) for an edit with the same content, so use this to skip the last edit. It is true if there was no preview or more chunks arrived after it — true means “may differ”. If you throttle edits so the last preview comes before the last chunk, it is true even when the final output is the same; in that case compare against the last string you sent.

Source

pub fn close_open(&self, out: &mut String)

Makes what has been received so far safe to send as is. It does not touch the state, so streaming continues after appending it.

Emphasis is held inside until its pair arrives, so it is already balanced, but a block’s opening markup (<blockquote>, <pre>, a heading’s <b>) goes out before the block ends — holding output until a code block ends would not be streaming. Callers that send the accumulated output to a channel midway (editing a message as tokens arrive) append this right before sending. Do not put it into the accumulated output itself — the next chunk continues from there.

use mdwire::{Channel, Streamer};

let mut s = Streamer::new(Channel::TelegramHtml);
let mut acc = String::new();
s.push_into("> 인용이 시작되고", &mut acc);

let mut snapshot = acc.clone();
s.close_open(&mut snapshot);          // safe to send now
assert_eq!(snapshot, "<blockquote>인용이 시작되고</blockquote>");

s.push_into("\n> 이어진다\n", &mut acc);  // the accumulated output just continues
s.finish_into(&mut acc);
assert_eq!(acc, "<blockquote>인용이 시작되고\n이어진다</blockquote>");

Auto Trait Implementations§

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.