use jetstream_wireformat::WireFormat;
use wasm_bindgen::prelude::*;
use crate::OkId;
const SECRET_EMOJI: char = '🔒';
const VS16: char = '\u{FE0F}'; const VS_BASE_FE: u32 = 0xFE00;
const VS_BASE_E01: u32 = 0xE0100;
const VS_RANGE_FE_MAX: u32 = 0xFE0F;
const VS_RANGE_E01_MAX: u32 = 0xE01EF;
const FE_RANGE_SIZE: u8 = 16;
#[wasm_bindgen]
impl OkId {
#[wasm_bindgen(js_name = toDisplaySafe)]
pub fn to_display_safe(self) -> String {
let mut bytes = vec![];
self.encode(&mut bytes).unwrap();
let mut result = String::from(SECRET_EMOJI);
result.push(VS16);
for byte in bytes {
result.push(byte_to_variation_selector(byte));
}
result
}
#[wasm_bindgen(js_name = fromDisplaySafe)]
pub fn from_display_safe(s: &str) -> Option<Self> {
let bytes = decode_variation_selectors(s)?;
WireFormat::decode(&mut bytes.as_slice()).ok()
}
}
const fn byte_to_variation_selector(byte: u8) -> char {
if byte < FE_RANGE_SIZE {
char::from_u32(VS_BASE_FE + byte as u32).unwrap()
} else {
char::from_u32(VS_BASE_E01 + (byte - FE_RANGE_SIZE) as u32).unwrap()
}
}
fn decode_variation_selectors(s: &str) -> Option<Vec<u8>> {
let mut chars = s.chars();
if chars.next() != Some(SECRET_EMOJI) {
return None;
}
if chars.clone().next() == Some(VS16) {
chars.next();
}
let mut result = Vec::new();
for ch in chars {
if let Some(byte) = variation_selector_to_byte(ch) {
result.push(byte);
}
}
Some(result)
}
fn variation_selector_to_byte(variation_selector: char) -> Option<u8> {
let code = variation_selector as u32;
if (VS_BASE_FE..=VS_RANGE_FE_MAX).contains(&code) {
Some((code - VS_BASE_FE) as u8)
} else if (VS_BASE_E01..=VS_RANGE_E01_MAX).contains(&code) {
Some((code - VS_BASE_E01 + FE_RANGE_SIZE as u32) as u8)
} else {
None
}
}