mathtex_editor_session/
tokens.rs1use std::collections::BTreeSet;
2use std::fmt;
3
4use mathtex_editor_core::{Document, Editor, MAX_HOST_TOKEN};
5
6use crate::UndoStack;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum TokenError {
11 TooLarge(u32),
13 Exhausted,
15}
16
17impl fmt::Display for TokenError {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 TokenError::TooLarge(t) => write!(f, "host box token {t} is above {MAX_HOST_TOKEN}"),
21 TokenError::Exhausted => write!(f, "every host box token up to {MAX_HOST_TOKEN} is taken"),
22 }
23 }
24}
25
26impl std::error::Error for TokenError {}
27
28#[derive(Debug, Clone)]
30pub struct TokenRegistry {
31 next: u32,
32 reserved: BTreeSet<u32>,
34}
35
36impl Default for TokenRegistry {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl TokenRegistry {
43 pub fn new() -> Self {
45 Self { next: 1, reserved: BTreeSet::new() }
46 }
47
48 pub fn mint(&mut self) -> Result<u32, TokenError> {
50 while self.next <= MAX_HOST_TOKEN {
51 let token = self.next;
52 self.next += 1;
53 if !self.reserved.remove(&token) {
54 return Ok(token);
55 }
56 }
57 Err(TokenError::Exhausted)
58 }
59
60 pub fn reserve(&mut self, token: u32) -> Result<(), TokenError> {
62 if token > MAX_HOST_TOKEN {
63 return Err(TokenError::TooLarge(token));
64 }
65 if token >= self.next {
66 self.reserved.insert(token);
67 }
68 Ok(())
69 }
70
71 pub fn reserve_document(&mut self, doc: &Document) {
73 for token in doc.host_tokens() {
74 let _ = self.reserve(token);
75 }
76 }
77
78 pub fn remint(&mut self, doc: &mut Document) -> Result<Vec<(u32, u32)>, TokenError> {
80 let mut pairs = Vec::new();
81 let mut failed = None;
82 doc.map_host_tokens(|old| match self.mint() {
83 Ok(new) => {
84 pairs.push((old, new));
85 new
86 }
87 Err(e) => {
88 failed = Some(e);
89 old
90 }
91 });
92 match failed {
93 Some(e) => Err(e),
94 None => Ok(pairs),
95 }
96 }
97
98 pub fn live(editor: &Editor, history: &UndoStack, clipboard: Option<&Document>) -> BTreeSet<u32> {
100 let mut live = editor.document().host_tokens();
101 for snapshot in history.snapshots() {
102 live.extend(snapshot.document.host_tokens());
103 }
104 if let Some(doc) = clipboard {
105 live.extend(doc.host_tokens());
106 }
107 live
108 }
109}