1use std::fmt::Debug;
2
3use num::{traits::AsPrimitive, FromPrimitive, Integer};
4use smallvec::{Array, SmallVec};
5
6use crate::SearchResult;
7
8pub trait Mergable<Cfg = ()> {
9 fn is_mergable(&self, _other: &Self, _conf: &Cfg) -> bool
10 where
11 Self: Sized,
12 {
13 false
14 }
15
16 fn merge(&mut self, _other: &Self, _conf: &Cfg)
17 where
18 Self: Sized,
19 {
20 unreachable!()
21 }
22}
23
24pub trait Sliceable {
28 fn slice(&self, from: usize, to: usize) -> Self;
29}
30
31#[derive(Debug, Clone, Copy)]
32pub struct Slice<'a, T> {
33 pub value: &'a T,
34 pub start: usize,
35 pub end: usize,
36}
37
38impl<T: Sliceable> Slice<'_, T> {
39 pub fn into_inner(&self) -> T {
40 self.value.slice(self.start, self.end)
41 }
42}
43
44#[allow(clippy::len_without_is_empty)]
45pub trait HasLength {
46 fn content_len(&self) -> usize;
50
51 fn atom_len(&self) -> usize {
56 self.content_len()
57 }
58}
59
60pub trait Rle<Cfg = ()>: HasLength + Sliceable + Mergable<Cfg> + Debug + Clone {}
61
62pub trait ZeroElement {
63 fn zero_element() -> Self;
64}
65
66impl<T: Default> ZeroElement for T {
67 fn zero_element() -> Self {
68 Default::default()
69 }
70}
71
72impl<T: HasLength + Sliceable + Mergable<Cfg> + Debug + Clone, Cfg> Rle<Cfg> for T {}
73
74pub trait HasIndex: HasLength {
75 type Int: GlobalIndex;
76 fn get_start_index(&self) -> Self::Int;
77
78 #[inline]
79 fn get_end_index(&self) -> Self::Int {
80 self.get_start_index() + Self::Int::from_usize(self.atom_len()).unwrap()
81 }
82}
83
84pub trait GlobalIndex:
85 Debug + Integer + Copy + Default + FromPrimitive + AsPrimitive<usize>
86{
87}
88
89impl<T: Debug + Integer + Copy + Default + FromPrimitive + AsPrimitive<usize>> GlobalIndex for T {}
90
91impl HasLength for String {
92 fn content_len(&self) -> usize {
93 self.len()
94 }
95}
96
97impl<T> HasLength for Vec<T> {
98 fn content_len(&self) -> usize {
99 self.len()
100 }
101}
102
103impl<T: Clone> Sliceable for Vec<T> {
104 fn slice(&self, from: usize, to: usize) -> Self {
105 self[from..to].to_vec()
106 }
107}
108
109impl Sliceable for String {
110 fn slice(&self, from: usize, to: usize) -> Self {
111 self[from..to].to_string()
112 }
113}
114
115pub trait RlePush<T> {
116 fn push_rle_element(&mut self, element: T);
117}
118
119pub trait RleCollection<T: HasIndex> {
120 fn start(&self) -> <T as HasIndex>::Int;
121 fn end(&self) -> <T as HasIndex>::Int;
122 fn sum_atom_len(&self) -> <T as HasIndex>::Int;
123 fn search_atom_index(&self, index: <T as HasIndex>::Int) -> usize;
124 fn get_by_atom_index(
125 &self,
126 index: <T as HasIndex>::Int,
127 ) -> Option<SearchResult<'_, T, <T as HasIndex>::Int>>;
128}
129
130impl<T: Mergable> RlePush<T> for Vec<T> {
131 fn push_rle_element(&mut self, element: T) {
132 match self.last_mut() {
133 Some(last) if last.is_mergable(&element, &()) => {
134 last.merge(&element, &());
135 }
136 _ => {
137 self.push(element);
138 }
139 }
140 }
141}
142
143impl<T: Mergable + HasIndex + HasLength> RleCollection<T> for Vec<T> {
144 fn search_atom_index(&self, index: <T as HasIndex>::Int) -> usize {
145 let mut start = 0;
146 let mut end = self.len() - 1;
147 while start < end {
148 let mid = (start + end) / 2;
149 match self[mid].get_start_index().cmp(&index) {
150 std::cmp::Ordering::Equal => {
151 start = mid;
152 break;
153 }
154 std::cmp::Ordering::Less => {
155 start = mid + 1;
156 }
157 std::cmp::Ordering::Greater => {
158 end = mid;
159 }
160 }
161 }
162
163 if index < self[start].get_start_index() {
164 start -= 1;
165 }
166 start
167 }
168
169 fn get_by_atom_index(
170 &self,
171 index: <T as HasIndex>::Int,
172 ) -> Option<SearchResult<'_, T, <T as HasIndex>::Int>> {
173 if index > self.end() {
174 return None;
175 }
176
177 let merged_index = self.search_atom_index(index);
178 let value = &self[merged_index];
179 Some(SearchResult {
180 merged_index,
181 element: value,
182 offset: index - self[merged_index].get_start_index(),
183 })
184 }
185
186 fn start(&self) -> <T as HasIndex>::Int {
187 self.first()
188 .map(|x| x.get_start_index())
189 .unwrap_or_default()
190 }
191
192 fn end(&self) -> <T as HasIndex>::Int {
193 self.last().map(|x| x.get_end_index()).unwrap_or_default()
194 }
195
196 fn sum_atom_len(&self) -> <T as HasIndex>::Int {
197 self.end() - self.start()
198 }
199}
200
201impl<A: Array> RlePush<A::Item> for SmallVec<A>
202where
203 A::Item: Mergable,
204{
205 fn push_rle_element(&mut self, element: A::Item) {
206 match self.last_mut() {
207 Some(last) if last.is_mergable(&element, &()) => {
208 last.merge(&element, &());
209 }
210 _ => {
211 self.push(element);
212 }
213 }
214 }
215}