fresh_core/
text_property.rs1use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::ops::Range;
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ts_rs::TS)]
14#[ts(export)]
15pub struct TextProperty {
16 pub start: usize,
18 pub end: usize,
20 #[ts(type = "Record<string, any>")]
22 pub properties: HashMap<String, serde_json::Value>,
23}
24
25impl TextProperty {
26 pub fn new(start: usize, end: usize) -> Self {
28 Self {
29 start,
30 end,
31 properties: HashMap::new(),
32 }
33 }
34
35 pub fn with_property(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
37 self.properties.insert(key.into(), value);
38 self
39 }
40
41 pub fn with_properties(mut self, props: HashMap<String, serde_json::Value>) -> Self {
43 self.properties.extend(props);
44 self
45 }
46
47 pub fn contains(&self, pos: usize) -> bool {
49 pos >= self.start && pos < self.end
50 }
51
52 pub fn overlaps(&self, range: &Range<usize>) -> bool {
54 self.start < range.end && self.end > range.start
55 }
56
57 pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
59 self.properties.get(key)
60 }
61
62 pub fn get_as<T: for<'de> Deserialize<'de>>(&self, key: &str) -> Option<T> {
64 self.properties
65 .get(key)
66 .and_then(|v| serde_json::from_value(v.clone()).ok())
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
72#[ts(export)]
73pub struct TextPropertyEntry {
74 pub text: String,
76 #[ts(type = "Record<string, any>")]
78 pub properties: HashMap<String, serde_json::Value>,
79}
80
81impl TextPropertyEntry {
82 pub fn text(text: impl Into<String>) -> Self {
84 Self {
85 text: text.into(),
86 properties: HashMap::new(),
87 }
88 }
89
90 pub fn with_property(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
92 self.properties.insert(key.into(), value);
93 self
94 }
95
96 pub fn with_properties(mut self, props: HashMap<String, serde_json::Value>) -> Self {
98 self.properties = props;
99 self
100 }
101}