use std::borrow::{Borrow, BorrowMut};
use std::collections::HashMap;
use std::fmt;
use std::fmt::Display;
use std::hash::Hash;
use wasm_bindgen::JsValue;
use web_sys;
pub struct Appender {
i: usize,
buffers: Vec<String>,
}
impl Appender {
pub fn new() -> Self {
return Appender {
i: 0,
buffers: vec![String::with_capacity(64)],
};
}
fn current(&mut self) -> &mut String {
&mut self.buffers[self.i]
}
fn assert_cap(&mut self, append_size: usize) {
let buf = self.current();
let cap = buf.capacity();
if buf.len() + append_size > cap {
if self.i == self.buffers.len() - 1 {
self.buffers.push(String::with_capacity(cap * 2));
} else {
self.i += 1;
}
}
}
pub fn clear(&mut self) {
self.i = 0;
for b in self.buffers.iter_mut() {
b.clear()
}
}
pub fn dump(&mut self) -> String {
self.buffers.concat()
}
}
impl fmt::Write for Appender {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.assert_cap(s.len());
self.current().write_str(s)
}
fn write_char(&mut self, c: char) -> fmt::Result {
self.assert_cap(1);
self.current().write_char(c)
}
}
#[derive(Default, Debug)]
pub struct LazyElement {
pub id: u64,
pub element: Option<web_sys::Element>,
}
impl LazyElement {
pub fn get(&mut self) -> Result<web_sys::Element, JsValue> {
match &mut self.element {
Some(el) => Ok(el.clone()),
None => {
match document().get_element_by_id(&format!("bh-{}", self.id)) {
Some(el) => {
self.element = Some(el.clone());
Ok(el)
}
None => {
Err(format!("element not found: bh-{}", self.id).into())
}
}
}
}
}
}
pub fn with_global<F, R, G>(
global: &'static std::thread::LocalKey<std::cell::RefCell<G>>,
func: F,
) -> R
where
F: FnOnce(&G) -> R,
{
global.with(|r| func(r.borrow().borrow()))
}
pub fn with_global_mut<F, R, G>(
global: &'static std::thread::LocalKey<std::cell::RefCell<G>>,
func: F,
) -> R
where
F: FnOnce(&mut G) -> R,
{
global.with(|r| func(r.borrow_mut().borrow_mut()))
}
#[derive(Default)]
pub struct TokenMap<T: Eq + Hash + Clone> {
forward: HashMap<u16, T>,
inverted: HashMap<T, u16>,
}
impl<T: Eq + Hash + Clone> TokenMap<T> {
pub fn get_token(&self, value: &T) -> Option<&u16> {
self.inverted.get(value)
}
pub fn get_value(&self, token: u16) -> &T {
self.forward.get(&token).expect("unset token lookup")
}
pub fn insert(&mut self, token: u16, value: T) {
self.forward.insert(token, value.clone());
self.inverted.insert(value, token);
}
}
#[derive(Default)]
pub struct IDGenerator {
counter: u16,
}
impl IDGenerator {
pub fn new(start_from: u16) -> Self {
Self {
counter: start_from,
}
}
pub fn new_id(&mut self, flag_highest: bool) -> u16 {
self.counter += 1;
let mut id = self.counter;
if flag_highest {
id |= 1 << 15;
}
return id;
}
#[inline]
pub fn is_flagged(id: u16) -> bool {
return id & (1 << 15) != 0;
}
}
pub fn html_escape(s: &str) -> String {
let mut escaped = String::with_capacity(s.len());
for ch in s.chars() {
match ch {
'&' => escaped += "&",
'\'' => {
escaped += "'"; }
'<' => {
escaped += "<";
}
'>' => {
escaped += ">";
}
'"' => {
escaped += """; }
_ => {
escaped.push(ch);
}
};
}
escaped
}
pub fn window() -> web_sys::Window {
web_sys::window().expect("no window global")
}
pub fn document() -> web_sys::Document {
window().document().expect("no document on window")
}
pub fn cast_error<T: Display>(e: T) -> JsValue {
JsValue::from(format!("{}", e))
}
pub trait WriteHTMLTo {
fn write_html_to<W: fmt::Write>(&mut self, w: &mut W) -> fmt::Result;
}