code_span/view/
mod.rs

1use std::{fmt::Debug, ops::Range};
2
3use serde::{Deserialize, Serialize};
4
5mod convert;
6pub mod iter;
7
8/// Save the given code and store additional information on each character
9///
10/// # Examples
11///
12/// ```
13/// use code_span::CodeView;
14/// let _: CodeView<&'static str> = CodeView::from("public static class MyClass {}");
15/// ```
16#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
17pub struct CodeView<T> {
18    text: String,
19    info: Vec<Option<T>>,
20}
21
22/// Each character of these code stores the same information
23///
24/// # Examples
25///
26/// ```
27/// use code_span::CodeSpan;
28/// CodeSpan { text: "public".to_string(), info: Some("keyword".to_string()) };
29/// ```
30#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
31pub struct CodeSpan<T> {
32    /// text
33    pub text: String,
34    /// info
35    pub info: Option<T>,
36}
37
38impl<T> CodeView<T> {
39    /// Create a piece of code with no information
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use code_span::CodeView;
45    /// let _: CodeView<&'static str> = CodeView::blank("public static class MyClass {}");
46    /// ```
47    pub fn blank(text: impl Into<String>) -> Self
48    where
49        T: Clone,
50    {
51        let text = text.into();
52        let count = text.chars().count();
53        Self { text, info: vec![None; count] }
54    }
55    /// Create a piece of code with specified information
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use code_span::CodeView;
61    /// let _: CodeView<&'static str> = CodeView::new("public".to_string(), vec![Some("keyword"); 6]);
62    /// ```
63    pub fn new(text: String, info: Vec<Option<T>>) -> Self {
64        assert_eq!(text.chars().count(), info.len());
65        Self { text, info }
66    }
67    /// Get original code
68    ///
69    /// # Examples
70    ///
71    /// ```
72    /// use code_span::CodeView;
73    /// let view: CodeView<&'static str> = CodeView::blank("public static class MyClass {}");
74    /// assert_eq!(view.get_text(), "public static class MyClass {}");
75    /// ```
76    #[inline]
77    pub fn get_text(&self) -> &str {
78        &self.text
79    }
80    /// Modify the original code
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use code_span::CodeView;
86    /// let mut view: CodeView<&'static str> = CodeView::blank("public static class MyClass {}");
87    /// assert_eq!(view.mut_text(), "public static class MyClass {}");
88    /// ```
89    #[inline]
90    pub fn mut_text(&mut self) -> &mut String {
91        &mut self.text
92    }
93    /// Get current information
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use code_span::CodeView;
99    /// let view: CodeView<&'static str> = CodeView::blank("public static class MyClass {}");
100    /// assert_eq!(view.get_info(), vec![None; 30]);
101    /// ```
102    #[inline]
103    pub fn get_info(&self) -> &[Option<T>] {
104        &self.info
105    }
106    /// Modify current information
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// use code_span::CodeView;
112    /// let mut view: CodeView<&'static str> = CodeView::blank("public");
113    /// view.mut_info().iter_mut().for_each(|v| *v = Some("keyword"));
114    /// ```
115    #[inline]
116    pub fn mut_info(&mut self) -> &mut [Option<T>] {
117        &mut self.info
118    }
119
120    /// Mark the information of a piece of code according to the character range
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// use code_span::CodeView;
126    /// let mut view = CodeView::blank("public static class MyClass {}");
127    /// view.mark_position(0, 6, Some("keyword"));
128    /// ```
129    pub fn mark_position(&mut self, start: usize, end: usize, info: Option<T>)
130    where
131        T: Clone,
132    {
133        debug_assert!(start <= end);
134        let end = self.info.len().min(end);
135        let items = unsafe { self.info.get_unchecked_mut(Range { start, end }) };
136        for item in items {
137            *item = info.clone()
138        }
139    }
140    /// Mark the information of a piece of code according to the byte range
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use code_span::CodeView;
146    /// let mut view = CodeView::blank("public static class MyClass {}");
147    /// view.mark_offset(0, 6, Some("keyword"));
148    /// ```
149    pub fn mark_offset(&mut self, start: usize, end: usize, info: Option<T>)
150    where
151        T: Clone,
152    {
153        debug_assert!(start <= end);
154        let end = self.text.len().min(end);
155        let start = self.text[..start].chars().count();
156        let end = start + self.text[start..end].chars().count();
157        self.mark_position(start, end, info)
158    }
159}