pub struct Streamer { /* private fields */ }Expand description
스트리밍 변환기.
조각을 넣으면 지금 안전하게 내보낼 수 있는 만큼만 돌려준다.
경계에 걸린 마크업(**굵 에서 끊긴 것)은 안에 남겨 두고 다음 조각을 기다린다.
이것이 이 라이브러리의 핵심이다 — 완성본 변환은 이미 남들이 푼 문제고,
경계 문제는 스트리밍을 하는 한 채널과 무관하게 생긴다.
§예
use mdwire::{Channel, Streamer};
let mut s = Streamer::new(Channel::TelegramHtml);
let mut out = String::new();
// 조각 경계가 `**` 한가운데를 지나가도 반쪽으로 나가지 않는다.
out.push_str(s.push("앞말 **굵"));
out.push_str(s.push("게** 뒷말"));
out.push_str(s.finish());
assert_eq!(out, "앞말 <b>굵게</b> 뒷말");Implementations§
Source§impl Streamer
impl Streamer
pub fn new(channel: Channel) -> Self
Sourcepub fn with_options(channel: Channel, options: Options) -> Self
pub fn with_options(channel: Channel, options: Options) -> Self
옵션을 주고 만든다 — 입력 방언 따위.
Sourcepub fn push(&mut self, chunk: &str) -> &str
pub fn push(&mut self, chunk: &str) -> &str
조각을 밀어 넣고, 지금 내보낼 수 있는 출력을 받는다.
돌려주는 슬라이스는 다음 호출 전까지만 유효하다. 할당을 아예 없애려면
Streamer::push_into 를 쓴다 — 둘은 같은 코드를 부른다(SPEC.md 5절).
Sourcepub fn push_into(&mut self, chunk: &str, out: &mut String)
pub fn push_into(&mut self, chunk: &str, out: &mut String)
호출자 버퍼에 직접 쓴다. 정본 서명 — 조각당 할당이 0 이다.
Sourcepub fn finish_into(&mut self, out: &mut String)
pub fn finish_into(&mut self, out: &mut String)
Streamer::finish 의 무할당 판.
Sourcepub fn preview(&mut self) -> &str
pub fn preview(&mut self) -> &str
지금 입력이 끝났다면 확정분 뒤에 붙을 꼬리. 누적본에 이걸 붙이면 그 자리에서 보낼 수
있는 모양이다 — Streamer::close_open 과 같은 자리에 들어가지만, 붙들고 있던 것까지
그린다: 열린 강조는 닫아서(**굵 → <b>굵</b>), 표는 지금까지 온 행으로, 코드 스팬은
닫아서. 누적본을 통째로 다시 그리는 쪽(React, 텔레그램 editMessageText, 슬랙
chat.update)의 기본값이다.
꼬리는 일괄 렌더와 같은 finish 경로라 문법은 늘 맞는다. 다만 추측이다 — 끝내 안
닫힌 코드 스팬이 글자로 되돌아가는 것처럼 뒤의 조각이 모양을 바꿀 수 있다. 끝난 뒤에
마지막 미리보기와 달라졌는지는 Streamer::revised 가 알려 준다. 누적본 자체에는
넣지 않는다.
비용은 지금 열린 블록 크기에 비례한다(엔진을 복제한다). 조각마다 부르지 말고 화면을 그릴 때 부른다.
use mdwire::{Channel, Streamer};
let mut s = Streamer::new(Channel::TelegramHtml);
let mut acc = String::new();
s.push_into("앞말 **굵", &mut acc);
assert_eq!(acc, "앞말 "); // 확정분은 여기까지
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()); // 마지막 화면이 곧 완성본Sourcepub fn preview_into(&mut self, out: &mut String)
pub fn preview_into(&mut self, out: &mut String)
Streamer::preview 를 호출자 버퍼에 덧붙인다.
Sourcepub fn revised(&self) -> bool
pub fn revised(&self) -> bool
완성본이 마지막 미리보기와 다른가 — finish 뒤에 본다. 거짓이면 마지막으로 그린
화면(누적본 + preview)이 곧 완성본이라 다시 그릴 필요가 없다. 텔레그램은 같은 내용으로
편집하면 400(“message is not modified”)을 주므로 이걸 보고 마지막 편집을 건너뛴다.
미리보기를 안 했거나 그 뒤에 조각이 더 왔으면 참이다 — 참은 “다를 수 있다” 는 뜻이다.
편집을 솎아 보내 마지막 미리보기가 마지막 조각보다 앞서면 완성본이 같아도 참이니, 그런
쪽은 마지막으로 보낸 문자열과 직접 비교한다.
Sourcepub fn close_open(&self, out: &mut String)
pub fn close_open(&self, out: &mut String)
지금까지 받은 것을 그대로 보내도 되게 만든다. 상태는 건드리지 않으므로 붙인 뒤에도 스트리밍은 이어진다.
강조는 짝이 맞을 때까지 안에 붙들려 있어 이미 균형이 맞지만, 블록의 여는
마크업(<blockquote>·<pre>·헤딩의 <b>)은 블록이 끝나기 전에 나간다 —
코드블록이 끝날 때까지 출력을 멈추면 스트리밍이 아니기 때문이다. 누적본을
중간에 채널로 보내는 쪽(토큰이 오는 대로 메시지를 편집하는 경우)은 보내기
직전에 이걸 덧붙인다. 누적본 자체에는 넣지 않는다 — 다음 조각이 이어진다.
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); // 지금 보내도 되는 모양
assert_eq!(snapshot, "<blockquote>인용이 시작되고</blockquote>");
s.push_into("\n> 이어진다\n", &mut acc); // 누적본은 그대로 이어진다
s.finish_into(&mut acc);
assert_eq!(acc, "<blockquote>인용이 시작되고\n이어진다</blockquote>");