use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::ops::Range;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ts_rs::TS)]
#[ts(export)]
pub struct TextProperty {
pub start: usize,
pub end: usize,
#[ts(type = "Record<string, any>")]
pub properties: HashMap<String, serde_json::Value>,
}
impl TextProperty {
pub fn new(start: usize, end: usize) -> Self {
Self {
start,
end,
properties: HashMap::new(),
}
}
pub fn with_property(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
self.properties.insert(key.into(), value);
self
}
pub fn with_properties(mut self, props: HashMap<String, serde_json::Value>) -> Self {
self.properties.extend(props);
self
}
pub fn contains(&self, pos: usize) -> bool {
pos >= self.start && pos < self.end
}
pub fn overlaps(&self, range: &Range<usize>) -> bool {
self.start < range.end && self.end > range.start
}
pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
self.properties.get(key)
}
pub fn get_as<T: for<'de> Deserialize<'de>>(&self, key: &str) -> Option<T> {
self.properties
.get(key)
.and_then(|v| serde_json::from_value(v.clone()).ok())
}
}
#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
#[ts(export)]
pub struct TextPropertyEntry {
pub text: String,
#[ts(type = "Record<string, any>")]
pub properties: HashMap<String, serde_json::Value>,
}
impl TextPropertyEntry {
pub fn text(text: impl Into<String>) -> Self {
Self {
text: text.into(),
properties: HashMap::new(),
}
}
pub fn with_property(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
self.properties.insert(key.into(), value);
self
}
pub fn with_properties(mut self, props: HashMap<String, serde_json::Value>) -> Self {
self.properties = props;
self
}
}