|
77 | 77 | /// however, Calcit is heavy in cloning(reference though... according real practice),
|
78 | 78 | /// so here we still choose `ref_get` for speed in Calcit project.
|
79 | 79 | pub fn get(&self, idx: usize) -> Option<&T> {
|
80 |
| - if self.is_empty() || idx >= self.len() { |
| 80 | + let l = self.len(); |
| 81 | + if l == 0 || idx >= l { |
81 | 82 | None
|
| 83 | + } else if idx == 0 { |
| 84 | + match self { |
| 85 | + Empty => None, |
| 86 | + Tree(t) => t.ref_first(), |
| 87 | + } |
| 88 | + } else if idx == l - 1 { |
| 89 | + match self { |
| 90 | + Empty => None, |
| 91 | + Tree(t) => t.ref_last(), |
| 92 | + } |
82 | 93 | } else {
|
83 | 94 | self.ref_get(idx)
|
84 | 95 | }
|
@@ -148,6 +159,8 @@ where
|
148 | 159 | Tree(t) => t.last(),
|
149 | 160 | }
|
150 | 161 | }
|
| 162 | + |
| 163 | + // at known index, update value |
151 | 164 | pub fn assoc(&self, idx: usize, item: T) -> Result<Self, String> {
|
152 | 165 | match self {
|
153 | 166 | Empty => Err(String::from("empty")),
|
@@ -208,7 +221,13 @@ where
|
208 | 221 | }
|
209 | 222 | }
|
210 | 223 |
|
211 |
| - Tree(t) => Ok(TernaryTreeList::Tree(t.insert(idx, item, after)?)), |
| 224 | + Tree(t) => { |
| 225 | + if after { |
| 226 | + Ok(TernaryTreeList::Tree(t.insert_after(idx, item)?)) |
| 227 | + } else { |
| 228 | + Ok(TernaryTreeList::Tree(t.insert_before(idx, item)?)) |
| 229 | + } |
| 230 | + } |
212 | 231 | }
|
213 | 232 | }
|
214 | 233 | pub fn assoc_before(&self, idx: usize, item: T) -> Result<Self, String> {
|
@@ -241,7 +260,7 @@ where
|
241 | 260 | pub fn append(&self, item: T) -> Self {
|
242 | 261 | match self {
|
243 | 262 | Empty => TernaryTreeList::Tree(TernaryTree::Leaf(item)),
|
244 |
| - Tree(t) => TernaryTreeList::Tree(t.append(item)), |
| 263 | + Tree(t) => TernaryTreeList::Tree(t.push_right(item)), |
245 | 264 | }
|
246 | 265 | }
|
247 | 266 | /// optimized for amortized `O(1)` performance at best cases
|
@@ -381,10 +400,33 @@ where
|
381 | 400 | }
|
382 | 401 |
|
383 | 402 | pub fn skip(&self, idx: usize) -> Result<Self, String> {
|
384 |
| - self.slice(idx, self.len()) |
| 403 | + // self.slice(idx, self.len()) |
| 404 | + |
| 405 | + match self { |
| 406 | + Empty => Ok(TernaryTreeList::Empty), |
| 407 | + Tree(t) => { |
| 408 | + let size = t.len(); |
| 409 | + match idx.cmp(&size) { |
| 410 | + Ordering::Equal => Ok(TernaryTreeList::Empty), |
| 411 | + Ordering::Greater => Err(format!("Skip range too large {} for {}", idx, self.format_inline())), |
| 412 | + Ordering::Less => Ok(TernaryTreeList::Tree(t.take_right(idx)?)), |
| 413 | + } |
| 414 | + } |
| 415 | + } |
385 | 416 | }
|
386 | 417 | pub fn take(&self, idx: usize) -> Result<Self, String> {
|
387 |
| - self.slice(0, idx) |
| 418 | + match self { |
| 419 | + Empty => Ok(TernaryTreeList::Empty), |
| 420 | + Tree(t) => { |
| 421 | + if idx == 0 { |
| 422 | + Ok(TernaryTreeList::Empty) |
| 423 | + } else if idx > self.len() { |
| 424 | + Err(format!("Take range too large {} for {}", idx, self.format_inline())) |
| 425 | + } else { |
| 426 | + Ok(TernaryTreeList::Tree(t.take_left(idx)?)) |
| 427 | + } |
| 428 | + } |
| 429 | + } |
388 | 430 | }
|
389 | 431 |
|
390 | 432 | pub fn reverse(&self) -> Self {
|
|
0 commit comments