1 use std::io; 2 use std::iter::FromIterator; 3 use std::ops::RangeBounds; 4 use std::ptr; 5 use std::sync::Arc; 6 7 use crate::crlf; 8 use crate::iter::{Bytes, Chars, Chunks, Lines}; 9 use crate::rope_builder::RopeBuilder; 10 use crate::slice::RopeSlice; 11 use crate::str_utils::{ 12 byte_to_char_idx, byte_to_line_idx, byte_to_utf16_surrogate_idx, char_to_byte_idx, 13 char_to_line_idx, line_to_byte_idx, line_to_char_idx, utf16_code_unit_to_char_idx, 14 }; 15 use crate::tree::{Count, Node, NodeChildren, TextInfo, MAX_BYTES, MIN_BYTES}; 16 use crate::{end_bound_to_num, start_bound_to_num, Error, Result}; 17 18 /// A utf8 text rope. 19 /// 20 /// The time complexity of nearly all edit and query operations on `Rope` are 21 /// worst-case `O(log N)` in the length of the rope. `Rope` is designed to 22 /// work efficiently even for huge (in the gigabytes) and pathological (all on 23 /// one line) texts. 24 /// 25 /// # Editing Operations 26 /// 27 /// The primary editing operations on `Rope` are insertion and removal of text. 28 /// For example: 29 /// 30 /// ``` 31 /// # use ropey::Rope; 32 /// # 33 /// let mut rope = Rope::from_str("Hello みんなさん!"); 34 /// rope.remove(6..11); 35 /// rope.insert(6, "world"); 36 /// 37 /// assert_eq!(rope, "Hello world!"); 38 /// ``` 39 /// 40 /// # Query Operations 41 /// 42 /// `Rope` provides a rich set of efficient query functions, including querying 43 /// rope length in bytes/`char`s/lines, fetching individual `char`s or lines, 44 /// and converting between byte/`char`/line indices. For example, to find the 45 /// starting `char` index of a given line: 46 /// 47 /// ``` 48 /// # use ropey::Rope; 49 /// # 50 /// let rope = Rope::from_str("Hello みんなさん!\nHow are you?\nThis text has multiple lines!"); 51 /// 52 /// assert_eq!(rope.line_to_char(0), 0); 53 /// assert_eq!(rope.line_to_char(1), 13); 54 /// assert_eq!(rope.line_to_char(2), 26); 55 /// ``` 56 /// 57 /// # Slicing 58 /// 59 /// You can take immutable slices of a `Rope` using `slice()`: 60 /// 61 /// ``` 62 /// # use ropey::Rope; 63 /// # 64 /// let mut rope = Rope::from_str("Hello みんなさん!"); 65 /// let middle = rope.slice(3..8); 66 /// 67 /// assert_eq!(middle, "lo みん"); 68 /// ``` 69 /// 70 /// # Cloning 71 /// 72 /// Cloning `Rope`s is extremely cheap, running in `O(1)` time and taking a 73 /// small constant amount of memory for the new clone, regardless of text size. 74 /// This is accomplished by data sharing between `Rope` clones. The memory 75 /// used by clones only grows incrementally as the their contents diverge due 76 /// to edits. All of this is thread safe, so clones can be sent freely 77 /// between threads. 78 /// 79 /// The primary intended use-case for this feature is to allow asynchronous 80 /// processing of `Rope`s. For example, saving a large document to disk in a 81 /// separate thread while the user continues to perform edits. 82 #[derive(Clone)] 83 pub struct Rope { 84 pub(crate) root: Arc<Node>, 85 } 86 87 impl Rope { 88 //----------------------------------------------------------------------- 89 // Constructors 90 91 /// Creates an empty `Rope`. 92 #[inline] new() -> Self93 pub fn new() -> Self { 94 Rope { 95 root: Arc::new(Node::new()), 96 } 97 } 98 99 /// Creates a `Rope` from a string slice. 100 /// 101 /// Runs in O(N) time. 102 #[inline] 103 #[allow(clippy::should_implement_trait)] from_str(text: &str) -> Self104 pub fn from_str(text: &str) -> Self { 105 RopeBuilder::new().build_at_once(text) 106 } 107 108 /// Creates a `Rope` from the output of a reader. 109 /// 110 /// This is a convenience function, and provides *no specific guarantees* 111 /// about performance or internal implementation aside from the runtime 112 /// complexity listed below. 113 /// 114 /// When more precise control over IO behavior, buffering, etc. is desired, 115 /// you should handle IO yourself and use [`RopeBuilder`] to build the 116 /// `Rope`. 117 /// 118 /// Runs in O(N) time. 119 /// 120 /// # Errors 121 /// 122 /// - If the reader returns an error, `from_reader` stops and returns 123 /// that error. 124 /// - If non-utf8 data is encountered, an IO error with kind 125 /// `InvalidData` is returned. 126 /// 127 /// Note: some data from the reader is likely consumed even if there is 128 /// an error. 129 #[allow(unused_mut)] from_reader<T: io::Read>(mut reader: T) -> io::Result<Self>130 pub fn from_reader<T: io::Read>(mut reader: T) -> io::Result<Self> { 131 const BUFFER_SIZE: usize = MAX_BYTES * 2; 132 let mut builder = RopeBuilder::new(); 133 let mut buffer = [0u8; BUFFER_SIZE]; 134 let mut fill_idx = 0; // How much `buffer` is currently filled with valid data 135 loop { 136 match reader.read(&mut buffer[fill_idx..]) { 137 Ok(read_count) => { 138 fill_idx += read_count; 139 140 // Determine how much of the buffer is valid utf8. 141 let valid_count = match std::str::from_utf8(&buffer[..fill_idx]) { 142 Ok(_) => fill_idx, 143 Err(e) => e.valid_up_to(), 144 }; 145 146 // Append the valid part of the buffer to the rope. 147 if valid_count > 0 { 148 // The unsafe block here is reinterpreting the bytes as 149 // utf8. This is safe because the bytes being 150 // reinterpreted have already been validated as utf8 151 // just above. 152 builder.append(unsafe { 153 std::str::from_utf8_unchecked(&buffer[..valid_count]) 154 }); 155 } 156 157 // Shift the un-read part of the buffer to the beginning. 158 if valid_count < fill_idx { 159 // The unsafe here is just used for efficiency. This 160 // can be replaced with a safe call to `copy_within()` 161 // on the slice once that API is stabalized in the 162 // standard library. 163 unsafe { 164 ptr::copy( 165 buffer.as_ptr().add(valid_count), 166 buffer.as_mut_ptr().offset(0), 167 fill_idx - valid_count, 168 ); 169 } 170 } 171 fill_idx -= valid_count; 172 173 if fill_idx == BUFFER_SIZE { 174 // Buffer is full and none of it could be consumed. Utf8 175 // codepoints don't get that large, so it's clearly not 176 // valid text. 177 return Err(io::Error::new( 178 io::ErrorKind::InvalidData, 179 "stream did not contain valid UTF-8", 180 )); 181 } 182 183 // If we're done reading 184 if read_count == 0 { 185 if fill_idx > 0 { 186 // We couldn't consume all data. 187 return Err(io::Error::new( 188 io::ErrorKind::InvalidData, 189 "stream contained invalid UTF-8", 190 )); 191 } else { 192 return Ok(builder.finish()); 193 } 194 } 195 } 196 197 Err(e) => { 198 // Read error 199 return Err(e); 200 } 201 } 202 } 203 } 204 205 //----------------------------------------------------------------------- 206 // Convenience output methods 207 208 /// Writes the contents of the `Rope` to a writer. 209 /// 210 /// This is a convenience function, and provides *no specific guarantees* 211 /// about performance or internal implementation aside from the runtime 212 /// complexity listed below. 213 /// 214 /// When more precise control over IO behavior, buffering, etc. is 215 /// desired, you should handle IO yourself and use the [`Chunks`] 216 /// iterator to iterate through the `Rope`'s contents. 217 /// 218 /// Runs in O(N) time. 219 /// 220 /// # Errors 221 /// 222 /// - If the writer returns an error, `write_to` stops and returns that 223 /// error. 224 /// 225 /// Note: some data may have been written even if an error is returned. 226 #[allow(unused_mut)] write_to<T: io::Write>(&self, mut writer: T) -> io::Result<()>227 pub fn write_to<T: io::Write>(&self, mut writer: T) -> io::Result<()> { 228 for chunk in self.chunks() { 229 writer.write_all(chunk.as_bytes())?; 230 } 231 232 Ok(()) 233 } 234 235 //----------------------------------------------------------------------- 236 // Informational methods 237 238 /// Total number of bytes in the `Rope`. 239 /// 240 /// Runs in O(1) time. 241 #[inline] len_bytes(&self) -> usize242 pub fn len_bytes(&self) -> usize { 243 self.root.byte_count() 244 } 245 246 /// Total number of chars in the `Rope`. 247 /// 248 /// Runs in O(1) time. 249 #[inline] len_chars(&self) -> usize250 pub fn len_chars(&self) -> usize { 251 self.root.char_count() 252 } 253 254 /// Total number of lines in the `Rope`. 255 /// 256 /// Runs in O(1) time. 257 #[inline] len_lines(&self) -> usize258 pub fn len_lines(&self) -> usize { 259 self.root.line_break_count() + 1 260 } 261 262 /// Total number of utf16 code units that would be in `Rope` if it were 263 /// encoded as utf16. 264 /// 265 /// Ropey stores text internally as utf8, but sometimes it is necessary 266 /// to interact with external APIs that still use utf16. This function is 267 /// primarily intended for such situations, and is otherwise not very 268 /// useful. 269 /// 270 /// Runs in O(1) time. 271 #[inline] len_utf16_cu(&self) -> usize272 pub fn len_utf16_cu(&self) -> usize { 273 let info = self.root.text_info(); 274 (info.chars + info.utf16_surrogates) as usize 275 } 276 277 //----------------------------------------------------------------------- 278 // Memory management methods 279 280 /// Total size of the `Rope`'s text buffer space, in bytes. 281 /// 282 /// This includes unoccupied text buffer space. You can calculate 283 /// the unoccupied space with `capacity() - len_bytes()`. In general, 284 /// there will always be some unoccupied buffer space. 285 /// 286 /// Runs in O(N) time. capacity(&self) -> usize287 pub fn capacity(&self) -> usize { 288 let mut byte_count = 0; 289 for chunk in self.chunks() { 290 byte_count += chunk.len().max(MAX_BYTES); 291 } 292 byte_count 293 } 294 295 /// Shrinks the `Rope`'s capacity to the minimum possible. 296 /// 297 /// This will rarely result in `capacity() == len_bytes()`. `Rope` 298 /// stores text in a sequence of fixed-capacity chunks, so an exact fit 299 /// only happens for texts that are both a precise multiple of that 300 /// capacity _and_ have code point boundaries that line up exactly with 301 /// the capacity boundaries. 302 /// 303 /// After calling this, the difference between `capacity()` and 304 /// `len_bytes()` is typically under 1KB per megabyte of text in the 305 /// `Rope`. 306 /// 307 /// **NOTE:** calling this on a `Rope` clone causes it to stop sharing 308 /// all data with its other clones. In such cases you will very likely 309 /// be _increasing_ total memory usage despite shrinking the `Rope`'s 310 /// capacity. 311 /// 312 /// Runs in O(N) time, and uses O(log N) additional space during 313 /// shrinking. shrink_to_fit(&mut self)314 pub fn shrink_to_fit(&mut self) { 315 let mut node_stack = Vec::new(); 316 let mut builder = RopeBuilder::new(); 317 318 node_stack.push(self.root.clone()); 319 *self = Rope::new(); 320 321 loop { 322 if node_stack.is_empty() { 323 break; 324 } 325 326 if node_stack.last().unwrap().is_leaf() { 327 builder.append(node_stack.last().unwrap().leaf_text()); 328 node_stack.pop(); 329 } else if node_stack.last().unwrap().child_count() == 0 { 330 node_stack.pop(); 331 } else { 332 let (_, next_node) = Arc::make_mut(node_stack.last_mut().unwrap()) 333 .children_mut() 334 .remove(0); 335 node_stack.push(next_node); 336 } 337 } 338 339 *self = builder.finish(); 340 } 341 342 //----------------------------------------------------------------------- 343 // Edit methods 344 345 /// Inserts `text` at char index `char_idx`. 346 /// 347 /// Runs in O(M + log N) time, where N is the length of the `Rope` and M 348 /// is the length of `text`. 349 /// 350 /// # Panics 351 /// 352 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 353 #[inline] insert(&mut self, char_idx: usize, text: &str)354 pub fn insert(&mut self, char_idx: usize, text: &str) { 355 // Bounds check 356 self.try_insert(char_idx, text).unwrap() 357 } 358 359 /// Inserts a single char `ch` at char index `char_idx`. 360 /// 361 /// Runs in O(log N) time. 362 /// 363 /// # Panics 364 /// 365 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 366 #[inline] insert_char(&mut self, char_idx: usize, ch: char)367 pub fn insert_char(&mut self, char_idx: usize, ch: char) { 368 self.try_insert_char(char_idx, ch).unwrap() 369 } 370 371 /// Private internal-only method that does a single insertion of 372 /// sufficiently small text. 373 /// 374 /// This only works correctly for insertion texts smaller than or equal to 375 /// `MAX_BYTES - 4`. 376 /// 377 /// Note that a lot of the complexity in this method comes from avoiding 378 /// splitting CRLF pairs and, when possible, avoiding re-scanning text for 379 /// text info. It is otherwise conceptually fairly straightforward. insert_internal(&mut self, char_idx: usize, ins_text: &str)380 fn insert_internal(&mut self, char_idx: usize, ins_text: &str) { 381 let mut ins_text = ins_text; 382 let mut left_seam = false; 383 let root_info = self.root.text_info(); 384 385 let (l_info, residual) = Arc::make_mut(&mut self.root).edit_chunk_at_char( 386 char_idx, 387 root_info, 388 |idx, cur_info, leaf_text| { 389 // First check if we have a left seam. 390 if idx == 0 && char_idx > 0 && ins_text.as_bytes()[0] == 0x0A { 391 left_seam = true; 392 ins_text = &ins_text[1..]; 393 // Early out if it was only an LF. 394 if ins_text.is_empty() { 395 return (cur_info, None); 396 } 397 } 398 399 // Find our byte index 400 let byte_idx = char_to_byte_idx(leaf_text, idx); 401 402 // No node splitting 403 if (leaf_text.len() + ins_text.len()) <= MAX_BYTES { 404 // Calculate new info without doing a full re-scan of cur_text 405 let new_info = { 406 // Get summed info of current text and to-be-inserted text 407 let mut info = cur_info + TextInfo::from_str(ins_text); 408 // Check for CRLF pairs on the insertion seams, and 409 // adjust line break counts accordingly 410 if byte_idx > 0 { 411 if leaf_text.as_bytes()[byte_idx - 1] == 0x0D 412 && ins_text.as_bytes()[0] == 0x0A 413 { 414 info.line_breaks -= 1; 415 } 416 if byte_idx < leaf_text.len() 417 && leaf_text.as_bytes()[byte_idx - 1] == 0x0D 418 && leaf_text.as_bytes()[byte_idx] == 0x0A 419 { 420 info.line_breaks += 1; 421 } 422 } 423 if byte_idx < leaf_text.len() 424 && *ins_text.as_bytes().last().unwrap() == 0x0D 425 && leaf_text.as_bytes()[byte_idx] == 0x0A 426 { 427 info.line_breaks -= 1; 428 } 429 info 430 }; 431 // Insert the text and return the new info 432 leaf_text.insert_str(byte_idx, ins_text); 433 (new_info, None) 434 } 435 // We're splitting the node 436 else { 437 let r_text = leaf_text.insert_str_split(byte_idx, ins_text); 438 let l_text_info = TextInfo::from_str(&leaf_text); 439 if r_text.len() > 0 { 440 let r_text_info = TextInfo::from_str(&r_text); 441 ( 442 l_text_info, 443 Some((r_text_info, Arc::new(Node::Leaf(r_text)))), 444 ) 445 } else { 446 // Leaf couldn't be validly split, so leave it oversized 447 (l_text_info, None) 448 } 449 } 450 }, 451 ); 452 453 // Handle root splitting, if any. 454 if let Some((r_info, r_node)) = residual { 455 let mut l_node = Arc::new(Node::new()); 456 std::mem::swap(&mut l_node, &mut self.root); 457 458 let mut children = NodeChildren::new(); 459 children.push((l_info, l_node)); 460 children.push((r_info, r_node)); 461 462 *Arc::make_mut(&mut self.root) = Node::Internal(children); 463 } 464 465 // Insert the LF to the left. 466 // TODO: this code feels fairly redundant with above. Can we DRY this 467 // better? 468 if left_seam { 469 // Do the insertion 470 let root_info = self.root.text_info(); 471 let (l_info, residual) = Arc::make_mut(&mut self.root).edit_chunk_at_char( 472 char_idx - 1, 473 root_info, 474 |_, cur_info, leaf_text| { 475 let byte_idx = leaf_text.len(); 476 477 // No node splitting 478 if (leaf_text.len() + ins_text.len()) <= MAX_BYTES { 479 // Calculate new info without doing a full re-scan of cur_text 480 let mut new_info = cur_info; 481 new_info.bytes += 1; 482 new_info.chars += 1; 483 if *leaf_text.as_bytes().last().unwrap() != 0x0D { 484 new_info.line_breaks += 1; 485 } 486 // Insert the text and return the new info 487 leaf_text.insert_str(byte_idx, "\n"); 488 (new_info, None) 489 } 490 // We're splitting the node 491 else { 492 let r_text = leaf_text.insert_str_split(byte_idx, "\n"); 493 let l_text_info = TextInfo::from_str(&leaf_text); 494 if r_text.len() > 0 { 495 let r_text_info = TextInfo::from_str(&r_text); 496 ( 497 l_text_info, 498 Some((r_text_info, Arc::new(Node::Leaf(r_text)))), 499 ) 500 } else { 501 // Leaf couldn't be validly split, so leave it oversized 502 (l_text_info, None) 503 } 504 } 505 }, 506 ); 507 508 // Handle root splitting, if any. 509 if let Some((r_info, r_node)) = residual { 510 let mut l_node = Arc::new(Node::new()); 511 std::mem::swap(&mut l_node, &mut self.root); 512 513 let mut children = NodeChildren::new(); 514 children.push((l_info, l_node)); 515 children.push((r_info, r_node)); 516 517 *Arc::make_mut(&mut self.root) = Node::Internal(children); 518 } 519 } 520 } 521 522 /// Removes the text in the given char index range. 523 /// 524 /// Uses range syntax, e.g. `2..7`, `2..`, etc. The range is in `char` 525 /// indices. 526 /// 527 /// Runs in O(M + log N) time, where N is the length of the `Rope` and M 528 /// is the length of the range being removed. 529 /// 530 /// # Example 531 /// 532 /// ``` 533 /// # use ropey::Rope; 534 /// let mut rope = Rope::from_str("Hello world!"); 535 /// rope.remove(5..); 536 /// 537 /// assert_eq!("Hello", rope); 538 /// ``` 539 /// 540 /// # Panics 541 /// 542 /// Panics if the start of the range is greater than the end, or if the 543 /// end is out of bounds (i.e. `end > len_chars()`). remove<R>(&mut self, char_range: R) where R: RangeBounds<usize>,544 pub fn remove<R>(&mut self, char_range: R) 545 where 546 R: RangeBounds<usize>, 547 { 548 self.try_remove(char_range).unwrap() 549 } 550 551 /// Splits the `Rope` at `char_idx`, returning the right part of 552 /// the split. 553 /// 554 /// Runs in O(log N) time. 555 /// 556 /// # Panics 557 /// 558 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). split_off(&mut self, char_idx: usize) -> Self559 pub fn split_off(&mut self, char_idx: usize) -> Self { 560 self.try_split_off(char_idx).unwrap() 561 } 562 563 /// Appends a `Rope` to the end of this one, consuming the other `Rope`. 564 /// 565 /// Runs in O(log N) time. append(&mut self, other: Self)566 pub fn append(&mut self, other: Self) { 567 if self.len_chars() == 0 { 568 // Special case 569 let mut other = other; 570 std::mem::swap(self, &mut other); 571 } else if other.len_chars() > 0 { 572 let left_info = self.root.text_info(); 573 let right_info = other.root.text_info(); 574 575 let seam_byte_i = if other.char(0) == '\n' { 576 Some(left_info.bytes) 577 } else { 578 None 579 }; 580 581 let l_depth = self.root.depth(); 582 let r_depth = other.root.depth(); 583 584 if l_depth > r_depth { 585 let extra = 586 Arc::make_mut(&mut self.root).append_at_depth(other.root, l_depth - r_depth); 587 if let Some(node) = extra { 588 let mut children = NodeChildren::new(); 589 children.push((self.root.text_info(), Arc::clone(&self.root))); 590 children.push((node.text_info(), node)); 591 self.root = Arc::new(Node::Internal(children)); 592 } 593 } else { 594 let mut other = other; 595 let extra = Arc::make_mut(&mut other.root) 596 .prepend_at_depth(Arc::clone(&self.root), r_depth - l_depth); 597 if let Some(node) = extra { 598 let mut children = NodeChildren::new(); 599 children.push((node.text_info(), node)); 600 children.push((other.root.text_info(), Arc::clone(&other.root))); 601 other.root = Arc::new(Node::Internal(children)); 602 } 603 *self = other; 604 }; 605 606 // Fix up any mess left behind. 607 let root = Arc::make_mut(&mut self.root); 608 if let Some(i) = seam_byte_i { 609 root.fix_crlf_seam(i, true); 610 } 611 if (left_info.bytes as usize) < MIN_BYTES || (right_info.bytes as usize) < MIN_BYTES { 612 root.fix_tree_seam(left_info.chars as usize); 613 } 614 self.pull_up_singular_nodes(); 615 } 616 } 617 618 //----------------------------------------------------------------------- 619 // Index conversion methods 620 621 /// Returns the char index of the given byte. 622 /// 623 /// Notes: 624 /// 625 /// - If the byte is in the middle of a multi-byte char, returns the 626 /// index of the char that the byte belongs to. 627 /// - `byte_idx` can be one-past-the-end, which will return 628 /// one-past-the-end char index. 629 /// 630 /// Runs in O(log N) time. 631 /// 632 /// # Panics 633 /// 634 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx > len_bytes()`). 635 #[inline] byte_to_char(&self, byte_idx: usize) -> usize636 pub fn byte_to_char(&self, byte_idx: usize) -> usize { 637 self.try_byte_to_char(byte_idx).unwrap() 638 } 639 640 /// Returns the line index of the given byte. 641 /// 642 /// Notes: 643 /// 644 /// - Lines are zero-indexed. This is functionally equivalent to 645 /// counting the line endings before the specified byte. 646 /// - `byte_idx` can be one-past-the-end, which will return the 647 /// last line index. 648 /// 649 /// Runs in O(log N) time. 650 /// 651 /// # Panics 652 /// 653 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx > len_bytes()`). 654 #[inline] byte_to_line(&self, byte_idx: usize) -> usize655 pub fn byte_to_line(&self, byte_idx: usize) -> usize { 656 self.try_byte_to_line(byte_idx).unwrap() 657 } 658 659 /// Returns the byte index of the given char. 660 /// 661 /// Notes: 662 /// 663 /// - `char_idx` can be one-past-the-end, which will return 664 /// one-past-the-end byte index. 665 /// 666 /// Runs in O(log N) time. 667 /// 668 /// # Panics 669 /// 670 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 671 #[inline] char_to_byte(&self, char_idx: usize) -> usize672 pub fn char_to_byte(&self, char_idx: usize) -> usize { 673 self.try_char_to_byte(char_idx).unwrap() 674 } 675 676 /// Returns the line index of the given char. 677 /// 678 /// Notes: 679 /// 680 /// - Lines are zero-indexed. This is functionally equivalent to 681 /// counting the line endings before the specified char. 682 /// - `char_idx` can be one-past-the-end, which will return the 683 /// last line index. 684 /// 685 /// Runs in O(log N) time. 686 /// 687 /// # Panics 688 /// 689 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 690 #[inline] char_to_line(&self, char_idx: usize) -> usize691 pub fn char_to_line(&self, char_idx: usize) -> usize { 692 self.try_char_to_line(char_idx).unwrap() 693 } 694 695 /// Returns the utf16 code unit index of the given char. 696 /// 697 /// Ropey stores text internally as utf8, but sometimes it is necessary 698 /// to interact with external APIs that still use utf16. This function is 699 /// primarily intended for such situations, and is otherwise not very 700 /// useful. 701 /// 702 /// Runs in O(log N) time. 703 /// 704 /// # Panics 705 /// 706 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 707 #[inline] char_to_utf16_cu(&self, char_idx: usize) -> usize708 pub fn char_to_utf16_cu(&self, char_idx: usize) -> usize { 709 self.try_char_to_utf16_cu(char_idx).unwrap() 710 } 711 712 /// Returns the char index of the given utf16 code unit. 713 /// 714 /// Ropey stores text internally as utf8, but sometimes it is necessary 715 /// to interact with external APIs that still use utf16. This function is 716 /// primarily intended for such situations, and is otherwise not very 717 /// useful. 718 /// 719 /// Note: if the utf16 code unit is in the middle of a char, returns the 720 /// index of the char that it belongs to. 721 /// 722 /// Runs in O(log N) time. 723 /// 724 /// # Panics 725 /// 726 /// Panics if `utf16_cu_idx` is out of bounds 727 /// (i.e. `utf16_cu_idx > len_utf16_cu()`). 728 #[inline] utf16_cu_to_char(&self, utf16_cu_idx: usize) -> usize729 pub fn utf16_cu_to_char(&self, utf16_cu_idx: usize) -> usize { 730 self.try_utf16_cu_to_char(utf16_cu_idx).unwrap() 731 } 732 733 /// Returns the byte index of the start of the given line. 734 /// 735 /// Notes: 736 /// 737 /// - Lines are zero-indexed. 738 /// - `line_idx` can be one-past-the-end, which will return 739 /// one-past-the-end byte index. 740 /// 741 /// Runs in O(log N) time. 742 /// 743 /// # Panics 744 /// 745 /// Panics if `line_idx` is out of bounds (i.e. `line_idx > len_lines()`). 746 #[inline] line_to_byte(&self, line_idx: usize) -> usize747 pub fn line_to_byte(&self, line_idx: usize) -> usize { 748 self.try_line_to_byte(line_idx).unwrap() 749 } 750 751 /// Returns the char index of the start of the given line. 752 /// 753 /// Notes: 754 /// 755 /// - Lines are zero-indexed. 756 /// - `line_idx` can be one-past-the-end, which will return 757 /// one-past-the-end char index. 758 /// 759 /// Runs in O(log N) time. 760 /// 761 /// # Panics 762 /// 763 /// Panics if `line_idx` is out of bounds (i.e. `line_idx > len_lines()`). 764 #[inline] line_to_char(&self, line_idx: usize) -> usize765 pub fn line_to_char(&self, line_idx: usize) -> usize { 766 self.try_line_to_char(line_idx).unwrap() 767 } 768 769 //----------------------------------------------------------------------- 770 // Fetch methods 771 772 /// Returns the byte at `byte_idx`. 773 /// 774 /// Runs in O(log N) time. 775 /// 776 /// # Panics 777 /// 778 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx >= len_bytes()`). 779 #[inline] byte(&self, byte_idx: usize) -> u8780 pub fn byte(&self, byte_idx: usize) -> u8 { 781 // Bounds check 782 if let Some(out) = self.get_byte(byte_idx) { 783 out 784 } else { 785 panic!( 786 "Attempt to index past end of Rope: byte index {}, Rope byte length {}", 787 byte_idx, 788 self.len_bytes() 789 ); 790 } 791 } 792 793 /// Returns the char at `char_idx`. 794 /// 795 /// Runs in O(log N) time. 796 /// 797 /// # Panics 798 /// 799 /// Panics if `char_idx` is out of bounds (i.e. `char_idx >= len_chars()`). 800 #[inline] char(&self, char_idx: usize) -> char801 pub fn char(&self, char_idx: usize) -> char { 802 if let Some(out) = self.get_char(char_idx) { 803 out 804 } else { 805 panic!( 806 "Attempt to index past end of Rope: char index {}, Rope char length {}", 807 char_idx, 808 self.len_chars() 809 ); 810 } 811 } 812 813 /// Returns the line at `line_idx`. 814 /// 815 /// Note: lines are zero-indexed. 816 /// 817 /// Runs in O(log N) time. 818 /// 819 /// # Panics 820 /// 821 /// Panics if `line_idx` is out of bounds (i.e. `line_idx >= len_lines()`). 822 #[inline] line(&self, line_idx: usize) -> RopeSlice823 pub fn line(&self, line_idx: usize) -> RopeSlice { 824 if let Some(out) = self.get_line(line_idx) { 825 out 826 } else { 827 let len_lines = self.len_lines(); 828 panic!( 829 "Attempt to index past end of Rope: line index {}, Rope line length {}", 830 line_idx, len_lines 831 ); 832 } 833 } 834 835 /// Returns the chunk containing the given byte index. 836 /// 837 /// Also returns the byte and char indices of the beginning of the chunk 838 /// and the index of the line that the chunk starts on. 839 /// 840 /// Note: for convenience, a one-past-the-end `byte_idx` returns the last 841 /// chunk of the `RopeSlice`. 842 /// 843 /// The return value is organized as 844 /// `(chunk, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 845 /// 846 /// Runs in O(log N) time. 847 /// 848 /// # Panics 849 /// 850 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx > len_bytes()`). 851 #[inline] chunk_at_byte(&self, byte_idx: usize) -> (&str, usize, usize, usize)852 pub fn chunk_at_byte(&self, byte_idx: usize) -> (&str, usize, usize, usize) { 853 // Bounds check 854 if let Some(out) = self.get_chunk_at_byte(byte_idx) { 855 out 856 } else { 857 panic!( 858 "Attempt to index past end of Rope: byte index {}, Rope byte length {}", 859 byte_idx, 860 self.len_bytes() 861 ); 862 } 863 } 864 865 /// Returns the chunk containing the given char index. 866 /// 867 /// Also returns the byte and char indices of the beginning of the chunk 868 /// and the index of the line that the chunk starts on. 869 /// 870 /// Note: for convenience, a one-past-the-end `char_idx` returns the last 871 /// chunk of the `RopeSlice`. 872 /// 873 /// The return value is organized as 874 /// `(chunk, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 875 /// 876 /// Runs in O(log N) time. 877 /// 878 /// # Panics 879 /// 880 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 881 #[inline] chunk_at_char(&self, char_idx: usize) -> (&str, usize, usize, usize)882 pub fn chunk_at_char(&self, char_idx: usize) -> (&str, usize, usize, usize) { 883 if let Some(out) = self.get_chunk_at_char(char_idx) { 884 out 885 } else { 886 panic!( 887 "Attempt to index past end of Rope: char index {}, Rope char length {}", 888 char_idx, 889 self.len_chars() 890 ); 891 } 892 } 893 894 /// Returns the chunk containing the given line break. 895 /// 896 /// Also returns the byte and char indices of the beginning of the chunk 897 /// and the index of the line that the chunk starts on. 898 /// 899 /// Note: for convenience, both the beginning and end of the rope are 900 /// considered line breaks for the purposes of indexing. For example, in 901 /// the string `"Hello \n world!"` 0 would give the first chunk, 1 would 902 /// give the chunk containing the newline character, and 2 would give the 903 /// last chunk. 904 /// 905 /// The return value is organized as 906 /// `(chunk, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 907 /// 908 /// Runs in O(log N) time. 909 /// 910 /// # Panics 911 /// 912 /// Panics if `line_break_idx` is out of bounds (i.e. `line_break_idx > len_lines()`). 913 #[inline] chunk_at_line_break(&self, line_break_idx: usize) -> (&str, usize, usize, usize)914 pub fn chunk_at_line_break(&self, line_break_idx: usize) -> (&str, usize, usize, usize) { 915 if let Some(out) = self.get_chunk_at_line_break(line_break_idx) { 916 out 917 } else { 918 panic!( 919 "Attempt to index past end of Rope: line break index {}, max index {}", 920 line_break_idx, 921 self.len_lines() 922 ); 923 } 924 } 925 926 //----------------------------------------------------------------------- 927 // Slicing 928 929 /// Gets an immutable slice of the `Rope`. 930 /// 931 /// Uses range syntax, e.g. `2..7`, `2..`, etc. 932 /// 933 /// # Example 934 /// 935 /// ``` 936 /// # use ropey::Rope; 937 /// let rope = Rope::from_str("Hello world!"); 938 /// let slice = rope.slice(..5); 939 /// 940 /// assert_eq!("Hello", slice); 941 /// ``` 942 /// 943 /// Runs in O(log N) time. 944 /// 945 /// # Panics 946 /// 947 /// Panics if the start of the range is greater than the end, or if the 948 /// end is out of bounds (i.e. `end > len_chars()`). 949 #[inline] slice<R>(&self, char_range: R) -> RopeSlice where R: RangeBounds<usize>,950 pub fn slice<R>(&self, char_range: R) -> RopeSlice 951 where 952 R: RangeBounds<usize>, 953 { 954 self.get_slice(char_range).unwrap() 955 } 956 957 //----------------------------------------------------------------------- 958 // Iterator methods 959 960 /// Creates an iterator over the bytes of the `Rope`. 961 /// 962 /// Runs in O(log N) time. 963 #[inline] bytes(&self) -> Bytes964 pub fn bytes(&self) -> Bytes { 965 Bytes::new(&self.root) 966 } 967 968 /// Creates an iterator over the bytes of the `Rope`, starting at byte 969 /// `byte_idx`. 970 /// 971 /// If `byte_idx == len_bytes()` then an iterator at the end of the 972 /// `Rope` is created (i.e. `next()` will return `None`). 973 /// 974 /// Runs in O(log N) time. 975 /// 976 /// # Panics 977 /// 978 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx > len_bytes()`). 979 #[inline] bytes_at(&self, byte_idx: usize) -> Bytes980 pub fn bytes_at(&self, byte_idx: usize) -> Bytes { 981 if let Some(out) = self.get_bytes_at(byte_idx) { 982 out 983 } else { 984 panic!( 985 "Attempt to index past end of Rope: byte index {}, Rope byte length {}", 986 byte_idx, 987 self.len_bytes() 988 ); 989 } 990 } 991 992 /// Creates an iterator over the chars of the `Rope`. 993 /// 994 /// Runs in O(log N) time. 995 #[inline] chars(&self) -> Chars996 pub fn chars(&self) -> Chars { 997 Chars::new(&self.root) 998 } 999 1000 /// Creates an iterator over the chars of the `Rope`, starting at char 1001 /// `char_idx`. 1002 /// 1003 /// If `char_idx == len_chars()` then an iterator at the end of the 1004 /// `Rope` is created (i.e. `next()` will return `None`). 1005 /// 1006 /// Runs in O(log N) time. 1007 /// 1008 /// # Panics 1009 /// 1010 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 1011 #[inline] chars_at(&self, char_idx: usize) -> Chars1012 pub fn chars_at(&self, char_idx: usize) -> Chars { 1013 if let Some(out) = self.get_chars_at(char_idx) { 1014 out 1015 } else { 1016 panic!( 1017 "Attempt to index past end of Rope: char index {}, Rope char length {}", 1018 char_idx, 1019 self.len_chars() 1020 ); 1021 } 1022 } 1023 1024 /// Creates an iterator over the lines of the `Rope`. 1025 /// 1026 /// Runs in O(log N) time. 1027 #[inline] lines(&self) -> Lines1028 pub fn lines(&self) -> Lines { 1029 Lines::new(&self.root) 1030 } 1031 1032 /// Creates an iterator over the lines of the `Rope`, starting at line 1033 /// `line_idx`. 1034 /// 1035 /// If `line_idx == len_lines()` then an iterator at the end of the 1036 /// `Rope` is created (i.e. `next()` will return `None`). 1037 /// 1038 /// Runs in O(log N) time. 1039 /// 1040 /// # Panics 1041 /// 1042 /// Panics if `line_idx` is out of bounds (i.e. `line_idx > len_lines()`). 1043 #[inline] lines_at(&self, line_idx: usize) -> Lines1044 pub fn lines_at(&self, line_idx: usize) -> Lines { 1045 if let Some(out) = self.get_lines_at(line_idx) { 1046 out 1047 } else { 1048 panic!( 1049 "Attempt to index past end of Rope: line index {}, Rope line length {}", 1050 line_idx, 1051 self.len_lines() 1052 ); 1053 } 1054 } 1055 1056 /// Creates an iterator over the chunks of the `Rope`. 1057 /// 1058 /// Runs in O(log N) time. 1059 #[inline] chunks(&self) -> Chunks1060 pub fn chunks(&self) -> Chunks { 1061 Chunks::new(&self.root) 1062 } 1063 1064 /// Creates an iterator over the chunks of the `Rope`, with the 1065 /// iterator starting at the chunk containing `byte_idx`. 1066 /// 1067 /// Also returns the byte and char indices of the beginning of the first 1068 /// chunk to be yielded, and the index of the line that chunk starts on. 1069 /// 1070 /// If `byte_idx == len_bytes()` an iterator at the end of the `Rope` 1071 /// (yielding `None` on a call to `next()`) is created. 1072 /// 1073 /// The return value is organized as 1074 /// `(iterator, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 1075 /// 1076 /// Runs in O(log N) time. 1077 /// 1078 /// # Panics 1079 /// 1080 /// Panics if `byte_idx` is out of bounds (i.e. `byte_idx > len_bytes()`). 1081 #[inline] chunks_at_byte(&self, byte_idx: usize) -> (Chunks, usize, usize, usize)1082 pub fn chunks_at_byte(&self, byte_idx: usize) -> (Chunks, usize, usize, usize) { 1083 if let Some(out) = self.get_chunks_at_byte(byte_idx) { 1084 out 1085 } else { 1086 panic!( 1087 "Attempt to index past end of Rope: byte index {}, Rope byte length {}", 1088 byte_idx, 1089 self.len_bytes() 1090 ); 1091 } 1092 } 1093 1094 /// Creates an iterator over the chunks of the `Rope`, with the 1095 /// iterator starting at the chunk containing `char_idx`. 1096 /// 1097 /// Also returns the byte and char indices of the beginning of the first 1098 /// chunk to be yielded, and the index of the line that chunk starts on. 1099 /// 1100 /// If `char_idx == len_chars()` an iterator at the end of the `Rope` 1101 /// (yielding `None` on a call to `next()`) is created. 1102 /// 1103 /// The return value is organized as 1104 /// `(iterator, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 1105 /// 1106 /// Runs in O(log N) time. 1107 /// 1108 /// # Panics 1109 /// 1110 /// Panics if `char_idx` is out of bounds (i.e. `char_idx > len_chars()`). 1111 #[inline] chunks_at_char(&self, char_idx: usize) -> (Chunks, usize, usize, usize)1112 pub fn chunks_at_char(&self, char_idx: usize) -> (Chunks, usize, usize, usize) { 1113 if let Some(out) = self.get_chunks_at_char(char_idx) { 1114 out 1115 } else { 1116 panic!( 1117 "Attempt to index past end of Rope: char index {}, Rope char length {}", 1118 char_idx, 1119 self.len_chars() 1120 ); 1121 } 1122 } 1123 1124 /// Creates an iterator over the chunks of the `Rope`, with the 1125 /// iterator starting at the chunk containing `line_break_idx`. 1126 /// 1127 /// Also returns the byte and char indices of the beginning of the first 1128 /// chunk to be yielded, and the index of the line that chunk starts on. 1129 /// 1130 /// Note: for convenience, both the beginning and end of the `Rope` are 1131 /// considered line breaks for the purposes of indexing. For example, in 1132 /// the string `"Hello \n world!"` 0 would create an iterator starting on 1133 /// the first chunk, 1 would create an iterator starting on the chunk 1134 /// containing the newline character, and 2 would create an iterator at 1135 /// the end of the `Rope` (yielding `None` on a call to `next()`). 1136 /// 1137 /// The return value is organized as 1138 /// `(iterator, chunk_byte_idx, chunk_char_idx, chunk_line_idx)`. 1139 /// 1140 /// Runs in O(log N) time. 1141 /// 1142 /// # Panics 1143 /// 1144 /// Panics if `line_break_idx` is out of bounds (i.e. `line_break_idx > len_lines()`). 1145 #[inline] chunks_at_line_break(&self, line_break_idx: usize) -> (Chunks, usize, usize, usize)1146 pub fn chunks_at_line_break(&self, line_break_idx: usize) -> (Chunks, usize, usize, usize) { 1147 if let Some(out) = self.get_chunks_at_line_break(line_break_idx) { 1148 out 1149 } else { 1150 panic!( 1151 "Attempt to index past end of Rope: line break index {}, max index {}", 1152 line_break_idx, 1153 self.len_lines() 1154 ); 1155 } 1156 } 1157 1158 //----------------------------------------------------------------------- 1159 // Debugging 1160 1161 /// NOT PART OF THE PUBLIC API (hidden from docs for a reason!) 1162 /// 1163 /// Debugging tool to make sure that all of the meta-data of the 1164 /// tree is consistent with the actual data. 1165 #[doc(hidden)] assert_integrity(&self)1166 pub fn assert_integrity(&self) { 1167 self.root.assert_integrity(); 1168 } 1169 1170 /// NOT PART OF THE PUBLIC API (hidden from docs for a reason!) 1171 /// 1172 /// Debugging tool to make sure that all of the following invariants 1173 /// hold true throughout the tree: 1174 /// 1175 /// - The tree is the same height everywhere. 1176 /// - All internal nodes have the minimum number of children. 1177 /// - All leaf nodes are non-empty. 1178 /// - CRLF pairs are never split over chunk boundaries. 1179 #[doc(hidden)] assert_invariants(&self)1180 pub fn assert_invariants(&self) { 1181 self.root.assert_balance(); 1182 self.root.assert_node_size(true); 1183 self.assert_crlf_seams(); 1184 } 1185 1186 /// Checks that CRLF pairs are never split over chunk boundaries. assert_crlf_seams(&self)1187 fn assert_crlf_seams(&self) { 1188 if self.chunks().count() > 0 { 1189 let mut itr = self.chunks(); 1190 let mut last_chunk = itr.next().unwrap(); 1191 for chunk in itr { 1192 if !chunk.is_empty() && !last_chunk.is_empty() { 1193 assert!(crlf::seam_is_break(last_chunk.as_bytes(), chunk.as_bytes())); 1194 last_chunk = chunk; 1195 } else if last_chunk.is_empty() { 1196 last_chunk = chunk; 1197 } 1198 } 1199 } 1200 } 1201 1202 //----------------------------------------------------------------------- 1203 // Internal utilities 1204 1205 /// Iteratively replaces the root node with its child if it only has 1206 /// one child. pull_up_singular_nodes(&mut self)1207 pub(crate) fn pull_up_singular_nodes(&mut self) { 1208 while (!self.root.is_leaf()) && self.root.child_count() == 1 { 1209 let child = if let Node::Internal(ref children) = *self.root { 1210 Arc::clone(&children.nodes()[0]) 1211 } else { 1212 unreachable!() 1213 }; 1214 1215 self.root = child; 1216 } 1217 } 1218 } 1219 1220 /// # Non-Panicking 1221 /// 1222 /// The methods in this impl block provide non-panicking versions of 1223 /// `Rope`'s panicking methods. They return either `Option::None` or 1224 /// `Result::Err()` when their panicking counterparts would have panicked. 1225 impl Rope { 1226 /// Non-panicking version of [`insert()`](Rope::insert). 1227 #[inline] try_insert(&mut self, char_idx: usize, text: &str) -> Result<()>1228 pub fn try_insert(&mut self, char_idx: usize, text: &str) -> Result<()> { 1229 // Bounds check 1230 if char_idx <= self.len_chars() { 1231 // We have three cases here: 1232 // 1. The insertion text is very large, in which case building a new 1233 // Rope out of it and splicing it into the existing Rope is most 1234 // efficient. 1235 // 2. The insertion text is somewhat large, in which case splitting it 1236 // up into chunks and repeatedly inserting them is the most 1237 // efficient. The splitting is necessary because the insertion code 1238 // only works correctly below a certain insertion size. 1239 // 3. The insertion text is small, in which case we can simply insert 1240 // it. 1241 // 1242 // Cases #2 and #3 are rolled into one case here, where case #3 just 1243 // results in the text being "split" into only one chunk. 1244 // 1245 // The boundary for what constitutes "very large" text was arrived at 1246 // experimentally, by testing at what point Rope build + splice becomes 1247 // faster than split + repeated insert. This constant is likely worth 1248 // revisiting from time to time as Ropey evolves. 1249 if text.len() > MAX_BYTES * 6 { 1250 // Case #1: very large text, build rope and splice it in. 1251 let text_rope = Rope::from_str(text); 1252 let right = self.split_off(char_idx); 1253 self.append(text_rope); 1254 self.append(right); 1255 } else { 1256 // Cases #2 and #3: split into chunks and repeatedly insert. 1257 let mut text = text; 1258 while !text.is_empty() { 1259 // Split a chunk off from the end of the text. 1260 // We do this from the end instead of the front so that 1261 // the repeated insertions can keep re-using the same 1262 // insertion point. 1263 let split_idx = crlf::find_good_split( 1264 text.len() - (MAX_BYTES - 4).min(text.len()), 1265 text.as_bytes(), 1266 false, 1267 ); 1268 let ins_text = &text[split_idx..]; 1269 text = &text[..split_idx]; 1270 1271 // Do the insertion. 1272 self.insert_internal(char_idx, ins_text); 1273 } 1274 } 1275 Ok(()) 1276 } else { 1277 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1278 } 1279 } 1280 1281 /// Non-panicking version of [`insert_char()`](Rope::insert_char). 1282 #[inline] try_insert_char(&mut self, char_idx: usize, ch: char) -> Result<()>1283 pub fn try_insert_char(&mut self, char_idx: usize, ch: char) -> Result<()> { 1284 // Bounds check 1285 if char_idx <= self.len_chars() { 1286 let mut buf = [0u8; 4]; 1287 Ok(self.insert_internal(char_idx, ch.encode_utf8(&mut buf))) 1288 } else { 1289 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1290 } 1291 } 1292 1293 /// Non-panicking version of [`remove()`](Rope::remove). try_remove<R>(&mut self, char_range: R) -> Result<()> where R: RangeBounds<usize>,1294 pub fn try_remove<R>(&mut self, char_range: R) -> Result<()> 1295 where 1296 R: RangeBounds<usize>, 1297 { 1298 let start_opt = start_bound_to_num(char_range.start_bound()); 1299 let end_opt = end_bound_to_num(char_range.end_bound()); 1300 let start = start_opt.unwrap_or(0); 1301 let end = end_opt.unwrap_or_else(|| self.len_chars()); 1302 if !(end.max(start) <= self.len_chars()) { 1303 Err(Error::CharRangeOutOfBounds( 1304 start_opt, 1305 end_opt, 1306 self.len_chars(), 1307 )) 1308 } else if !(start <= end) { 1309 Err(Error::CharRangeInvalid(start, end)) 1310 } else { 1311 // A special case that the rest of the logic doesn't handle 1312 // correctly. 1313 if start == 0 && end == self.len_chars() { 1314 self.root = Arc::new(Node::new()); 1315 return Ok(()); 1316 } 1317 1318 let root = Arc::make_mut(&mut self.root); 1319 1320 let root_info = root.text_info(); 1321 let (_, crlf_seam, needs_fix) = root.remove_char_range(start, end, root_info); 1322 1323 if crlf_seam { 1324 let seam_idx = root.char_to_text_info(start).bytes; 1325 root.fix_crlf_seam(seam_idx as Count, false); 1326 } 1327 1328 if needs_fix { 1329 root.fix_tree_seam(start); 1330 } 1331 1332 self.pull_up_singular_nodes(); 1333 Ok(()) 1334 } 1335 } 1336 1337 /// Non-panicking version of [`split_off()`](Rope::split_off). try_split_off(&mut self, char_idx: usize) -> Result<Self>1338 pub fn try_split_off(&mut self, char_idx: usize) -> Result<Self> { 1339 // Bounds check 1340 if char_idx <= self.len_chars() { 1341 if char_idx == 0 { 1342 // Special case 1 1343 let mut new_rope = Rope::new(); 1344 std::mem::swap(self, &mut new_rope); 1345 Ok(new_rope) 1346 } else if char_idx == self.len_chars() { 1347 // Special case 2 1348 Ok(Rope::new()) 1349 } else { 1350 // Do the split 1351 let mut new_rope = Rope { 1352 root: Arc::new(Arc::make_mut(&mut self.root).split(char_idx)), 1353 }; 1354 1355 // Fix up the edges 1356 Arc::make_mut(&mut self.root).zip_fix_right(); 1357 Arc::make_mut(&mut new_rope.root).zip_fix_left(); 1358 self.pull_up_singular_nodes(); 1359 new_rope.pull_up_singular_nodes(); 1360 1361 Ok(new_rope) 1362 } 1363 } else { 1364 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1365 } 1366 } 1367 1368 /// Non-panicking version of [`byte_to_char()`](Rope::byte_to_char). 1369 #[inline] try_byte_to_char(&self, byte_idx: usize) -> Result<usize>1370 pub fn try_byte_to_char(&self, byte_idx: usize) -> Result<usize> { 1371 // Bounds check 1372 if byte_idx <= self.len_bytes() { 1373 let (chunk, b, c, _) = self.chunk_at_byte(byte_idx); 1374 Ok(c + byte_to_char_idx(chunk, byte_idx - b)) 1375 } else { 1376 Err(Error::ByteIndexOutOfBounds(byte_idx, self.len_bytes())) 1377 } 1378 } 1379 1380 /// Non-panicking version of [`byte_to_line()`](Rope::byte_to_line). 1381 #[inline] try_byte_to_line(&self, byte_idx: usize) -> Result<usize>1382 pub fn try_byte_to_line(&self, byte_idx: usize) -> Result<usize> { 1383 // Bounds check 1384 if byte_idx <= self.len_bytes() { 1385 let (chunk, b, _, l) = self.chunk_at_byte(byte_idx); 1386 Ok(l + byte_to_line_idx(chunk, byte_idx - b)) 1387 } else { 1388 Err(Error::ByteIndexOutOfBounds(byte_idx, self.len_bytes())) 1389 } 1390 } 1391 1392 /// Non-panicking version of [`char_to_byte()`](Rope::char_to_byte). 1393 #[inline] try_char_to_byte(&self, char_idx: usize) -> Result<usize>1394 pub fn try_char_to_byte(&self, char_idx: usize) -> Result<usize> { 1395 // Bounds check 1396 if char_idx <= self.len_chars() { 1397 let (chunk, b, c, _) = self.chunk_at_char(char_idx); 1398 Ok(b + char_to_byte_idx(chunk, char_idx - c)) 1399 } else { 1400 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1401 } 1402 } 1403 1404 /// Non-panicking version of [`char_to_line()`](Rope::char_to_line). 1405 #[inline] try_char_to_line(&self, char_idx: usize) -> Result<usize>1406 pub fn try_char_to_line(&self, char_idx: usize) -> Result<usize> { 1407 // Bounds check 1408 if char_idx <= self.len_chars() { 1409 let (chunk, _, c, l) = self.chunk_at_char(char_idx); 1410 Ok(l + char_to_line_idx(chunk, char_idx - c)) 1411 } else { 1412 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1413 } 1414 } 1415 1416 /// Non-panicking version of [`char_to_utf16_cu()`](Rope::char_to_utf16_cu). 1417 #[inline] try_char_to_utf16_cu(&self, char_idx: usize) -> Result<usize>1418 pub fn try_char_to_utf16_cu(&self, char_idx: usize) -> Result<usize> { 1419 // Bounds check 1420 if char_idx <= self.len_chars() { 1421 let (chunk, chunk_start_info) = self.root.get_chunk_at_char(char_idx); 1422 let chunk_byte_idx = 1423 char_to_byte_idx(chunk, char_idx - chunk_start_info.chars as usize); 1424 let surrogate_count = byte_to_utf16_surrogate_idx(chunk, chunk_byte_idx); 1425 1426 Ok(char_idx + chunk_start_info.utf16_surrogates as usize + surrogate_count) 1427 } else { 1428 Err(Error::CharIndexOutOfBounds(char_idx, self.len_chars())) 1429 } 1430 } 1431 1432 /// Non-panicking version of [`utf16_cu_to_char()`](Rope::utf16_cu_to_char). 1433 #[inline] try_utf16_cu_to_char(&self, utf16_cu_idx: usize) -> Result<usize>1434 pub fn try_utf16_cu_to_char(&self, utf16_cu_idx: usize) -> Result<usize> { 1435 // Bounds check 1436 if utf16_cu_idx <= self.len_utf16_cu() { 1437 let (chunk, chunk_start_info) = self.root.get_chunk_at_utf16_code_unit(utf16_cu_idx); 1438 let chunk_utf16_cu_idx = utf16_cu_idx 1439 - (chunk_start_info.chars + chunk_start_info.utf16_surrogates) as usize; 1440 let chunk_char_idx = utf16_code_unit_to_char_idx(chunk, chunk_utf16_cu_idx); 1441 1442 Ok(chunk_start_info.chars as usize + chunk_char_idx) 1443 } else { 1444 Err(Error::Utf16IndexOutOfBounds( 1445 utf16_cu_idx, 1446 self.len_utf16_cu(), 1447 )) 1448 } 1449 } 1450 1451 /// Non-panicking version of [`line_to_byte()`](Rope::line_to_byte). 1452 #[inline] try_line_to_byte(&self, line_idx: usize) -> Result<usize>1453 pub fn try_line_to_byte(&self, line_idx: usize) -> Result<usize> { 1454 // Bounds check 1455 if line_idx <= self.len_lines() { 1456 if line_idx == self.len_lines() { 1457 Ok(self.len_bytes()) 1458 } else { 1459 let (chunk, b, _, l) = self.chunk_at_line_break(line_idx); 1460 Ok(b + line_to_byte_idx(chunk, line_idx - l)) 1461 } 1462 } else { 1463 Err(Error::LineIndexOutOfBounds(line_idx, self.len_lines())) 1464 } 1465 } 1466 1467 /// Non-panicking version of [`line_to_char()`](Rope::line_to_char). 1468 #[inline] try_line_to_char(&self, line_idx: usize) -> Result<usize>1469 pub fn try_line_to_char(&self, line_idx: usize) -> Result<usize> { 1470 // Bounds check 1471 if line_idx <= self.len_lines() { 1472 if line_idx == self.len_lines() { 1473 Ok(self.len_chars()) 1474 } else { 1475 let (chunk, _, c, l) = self.chunk_at_line_break(line_idx); 1476 Ok(c + line_to_char_idx(chunk, line_idx - l)) 1477 } 1478 } else { 1479 Err(Error::LineIndexOutOfBounds(line_idx, self.len_lines())) 1480 } 1481 } 1482 1483 /// Non-panicking version of [`byte()`](Rope::byte). 1484 #[inline] get_byte(&self, byte_idx: usize) -> Option<u8>1485 pub fn get_byte(&self, byte_idx: usize) -> Option<u8> { 1486 // Bounds check 1487 if byte_idx < self.len_bytes() { 1488 let (chunk, chunk_byte_idx, _, _) = self.chunk_at_byte(byte_idx); 1489 let chunk_rel_byte_idx = byte_idx - chunk_byte_idx; 1490 Some(chunk.as_bytes()[chunk_rel_byte_idx]) 1491 } else { 1492 None 1493 } 1494 } 1495 1496 /// Non-panicking version of [`char()`](Rope::char). 1497 #[inline] get_char(&self, char_idx: usize) -> Option<char>1498 pub fn get_char(&self, char_idx: usize) -> Option<char> { 1499 // Bounds check 1500 if char_idx < self.len_chars() { 1501 let (chunk, _, chunk_char_idx, _) = self.chunk_at_char(char_idx); 1502 let byte_idx = char_to_byte_idx(chunk, char_idx - chunk_char_idx); 1503 Some(chunk[byte_idx..].chars().next().unwrap()) 1504 } else { 1505 None 1506 } 1507 } 1508 1509 /// Non-panicking version of [`line()`](Rope::line). 1510 #[inline] get_line(&self, line_idx: usize) -> Option<RopeSlice>1511 pub fn get_line(&self, line_idx: usize) -> Option<RopeSlice> { 1512 use crate::slice::RSEnum; 1513 use crate::str_utils::{count_chars, count_utf16_surrogates}; 1514 1515 let len_lines = self.len_lines(); 1516 1517 // Bounds check 1518 if line_idx < len_lines { 1519 let (chunk_1, _, c1, l1) = self.chunk_at_line_break(line_idx); 1520 let (chunk_2, _, c2, l2) = self.chunk_at_line_break(line_idx + 1); 1521 if c1 == c2 { 1522 let text1 = &chunk_1[line_to_byte_idx(chunk_1, line_idx - l1)..]; 1523 let text2 = &text1[..line_to_byte_idx(text1, 1)]; 1524 Some(RopeSlice(RSEnum::Light { 1525 text: text2, 1526 char_count: count_chars(text2) as Count, 1527 utf16_surrogate_count: count_utf16_surrogates(text2) as Count, 1528 line_break_count: if line_idx == (len_lines - 1) { 0 } else { 1 }, 1529 })) 1530 } else { 1531 let start = c1 + line_to_char_idx(chunk_1, line_idx - l1); 1532 let end = c2 + line_to_char_idx(chunk_2, line_idx + 1 - l2); 1533 Some(self.slice(start..end)) 1534 } 1535 } else { 1536 None 1537 } 1538 } 1539 1540 /// Non-panicking version of [`chunk_at_byte()`](Rope::chunk_at_byte). 1541 #[inline] get_chunk_at_byte(&self, byte_idx: usize) -> Option<(&str, usize, usize, usize)>1542 pub fn get_chunk_at_byte(&self, byte_idx: usize) -> Option<(&str, usize, usize, usize)> { 1543 // Bounds check 1544 if byte_idx <= self.len_bytes() { 1545 let (chunk, info) = self.root.get_chunk_at_byte(byte_idx); 1546 Some(( 1547 chunk, 1548 info.bytes as usize, 1549 info.chars as usize, 1550 info.line_breaks as usize, 1551 )) 1552 } else { 1553 None 1554 } 1555 } 1556 1557 /// Non-panicking version of [`chunk_at_char()`](Rope::chunk_at_char). 1558 #[inline] get_chunk_at_char(&self, char_idx: usize) -> Option<(&str, usize, usize, usize)>1559 pub fn get_chunk_at_char(&self, char_idx: usize) -> Option<(&str, usize, usize, usize)> { 1560 // Bounds check 1561 if char_idx <= self.len_chars() { 1562 let (chunk, info) = self.root.get_chunk_at_char(char_idx); 1563 Some(( 1564 chunk, 1565 info.bytes as usize, 1566 info.chars as usize, 1567 info.line_breaks as usize, 1568 )) 1569 } else { 1570 None 1571 } 1572 } 1573 1574 /// Non-panicking version of [`chunk_at_line_break()`](Rope::chunk_at_line_break). 1575 #[inline] get_chunk_at_line_break( &self, line_break_idx: usize, ) -> Option<(&str, usize, usize, usize)>1576 pub fn get_chunk_at_line_break( 1577 &self, 1578 line_break_idx: usize, 1579 ) -> Option<(&str, usize, usize, usize)> { 1580 // Bounds check 1581 if line_break_idx <= self.len_lines() { 1582 let (chunk, info) = self.root.get_chunk_at_line_break(line_break_idx); 1583 Some(( 1584 chunk, 1585 info.bytes as usize, 1586 info.chars as usize, 1587 info.line_breaks as usize, 1588 )) 1589 } else { 1590 None 1591 } 1592 } 1593 1594 /// Non-panicking version of [`slice()`](Rope::slice). 1595 #[inline] get_slice<R>(&self, char_range: R) -> Option<RopeSlice> where R: RangeBounds<usize>,1596 pub fn get_slice<R>(&self, char_range: R) -> Option<RopeSlice> 1597 where 1598 R: RangeBounds<usize>, 1599 { 1600 let start = start_bound_to_num(char_range.start_bound()).unwrap_or(0); 1601 let end = end_bound_to_num(char_range.end_bound()).unwrap_or_else(|| self.len_chars()); 1602 1603 // Bounds check 1604 if start <= end && end <= self.len_chars() { 1605 Some(RopeSlice::new_with_range(&self.root, start, end)) 1606 } else { 1607 None 1608 } 1609 } 1610 1611 /// Non-panicking version of [`bytes_at()`](Rope::bytes_at). 1612 #[inline] get_bytes_at(&self, byte_idx: usize) -> Option<Bytes>1613 pub fn get_bytes_at(&self, byte_idx: usize) -> Option<Bytes> { 1614 // Bounds check 1615 if byte_idx <= self.len_bytes() { 1616 let info = self.root.text_info(); 1617 Some(Bytes::new_with_range_at( 1618 &self.root, 1619 byte_idx, 1620 (0, info.bytes as usize), 1621 (0, info.chars as usize), 1622 (0, info.line_breaks as usize + 1), 1623 )) 1624 } else { 1625 None 1626 } 1627 } 1628 1629 /// Non-panicking version of [`chars_at()`](Rope::chars_at). 1630 #[inline] get_chars_at(&self, char_idx: usize) -> Option<Chars>1631 pub fn get_chars_at(&self, char_idx: usize) -> Option<Chars> { 1632 // Bounds check 1633 if char_idx <= self.len_chars() { 1634 let info = self.root.text_info(); 1635 Some(Chars::new_with_range_at( 1636 &self.root, 1637 char_idx, 1638 (0, info.bytes as usize), 1639 (0, info.chars as usize), 1640 (0, info.line_breaks as usize + 1), 1641 )) 1642 } else { 1643 None 1644 } 1645 } 1646 1647 /// Non-panicking version of [`lines_at()`](Rope::lines_at). 1648 #[inline] get_lines_at(&self, line_idx: usize) -> Option<Lines>1649 pub fn get_lines_at(&self, line_idx: usize) -> Option<Lines> { 1650 // Bounds check 1651 if line_idx <= self.len_lines() { 1652 Some(Lines::new_with_range_at( 1653 &self.root, 1654 line_idx, 1655 (0, self.len_bytes()), 1656 (0, self.len_lines()), 1657 )) 1658 } else { 1659 None 1660 } 1661 } 1662 1663 /// Non-panicking version of [`chunks_at_byte()`](Rope::chunks_at_byte). 1664 #[inline] get_chunks_at_byte(&self, byte_idx: usize) -> Option<(Chunks, usize, usize, usize)>1665 pub fn get_chunks_at_byte(&self, byte_idx: usize) -> Option<(Chunks, usize, usize, usize)> { 1666 // Bounds check 1667 if byte_idx <= self.len_bytes() { 1668 Some(Chunks::new_with_range_at_byte( 1669 &self.root, 1670 byte_idx, 1671 (0, self.len_bytes()), 1672 (0, self.len_chars()), 1673 (0, self.len_lines()), 1674 )) 1675 } else { 1676 None 1677 } 1678 } 1679 1680 /// Non-panicking version of [`chunks_at_char()`](Rope::chunks_at_char). 1681 #[inline] get_chunks_at_char(&self, char_idx: usize) -> Option<(Chunks, usize, usize, usize)>1682 pub fn get_chunks_at_char(&self, char_idx: usize) -> Option<(Chunks, usize, usize, usize)> { 1683 // Bounds check 1684 if char_idx <= self.len_chars() { 1685 Some(Chunks::new_with_range_at_char( 1686 &self.root, 1687 char_idx, 1688 (0, self.len_bytes()), 1689 (0, self.len_chars()), 1690 (0, self.len_lines()), 1691 )) 1692 } else { 1693 None 1694 } 1695 } 1696 1697 /// Non-panicking version of [`chunks_at_line_break()`](Rope::chunks_at_line_break). 1698 #[inline] get_chunks_at_line_break( &self, line_break_idx: usize, ) -> Option<(Chunks, usize, usize, usize)>1699 pub fn get_chunks_at_line_break( 1700 &self, 1701 line_break_idx: usize, 1702 ) -> Option<(Chunks, usize, usize, usize)> { 1703 // Bounds check 1704 if line_break_idx <= self.len_lines() { 1705 Some(Chunks::new_with_range_at_line_break( 1706 &self.root, 1707 line_break_idx, 1708 (0, self.len_bytes()), 1709 (0, self.len_chars()), 1710 (0, self.len_lines()), 1711 )) 1712 } else { 1713 None 1714 } 1715 } 1716 } 1717 1718 //============================================================== 1719 // Conversion impls 1720 1721 impl<'a> From<&'a str> for Rope { 1722 #[inline] from(text: &'a str) -> Self1723 fn from(text: &'a str) -> Self { 1724 Rope::from_str(text) 1725 } 1726 } 1727 1728 impl<'a> From<std::borrow::Cow<'a, str>> for Rope { 1729 #[inline] from(text: std::borrow::Cow<'a, str>) -> Self1730 fn from(text: std::borrow::Cow<'a, str>) -> Self { 1731 Rope::from_str(&text) 1732 } 1733 } 1734 1735 impl From<String> for Rope { 1736 #[inline] from(text: String) -> Self1737 fn from(text: String) -> Self { 1738 Rope::from_str(&text) 1739 } 1740 } 1741 1742 /// Will share data where possible. 1743 /// 1744 /// Runs in O(log N) time. 1745 impl<'a> From<RopeSlice<'a>> for Rope { from(s: RopeSlice<'a>) -> Self1746 fn from(s: RopeSlice<'a>) -> Self { 1747 use crate::slice::RSEnum; 1748 match s { 1749 RopeSlice(RSEnum::Full { 1750 node, 1751 start_info, 1752 end_info, 1753 }) => { 1754 let mut rope = Rope { 1755 root: Arc::clone(node), 1756 }; 1757 1758 // Chop off right end if needed 1759 if end_info.chars < node.text_info().chars { 1760 { 1761 let root = Arc::make_mut(&mut rope.root); 1762 root.split(end_info.chars as usize); 1763 root.zip_fix_right(); 1764 } 1765 rope.pull_up_singular_nodes(); 1766 } 1767 1768 // Chop off left end if needed 1769 if start_info.chars > 0 { 1770 { 1771 let root = Arc::make_mut(&mut rope.root); 1772 *root = root.split(start_info.chars as usize); 1773 root.zip_fix_left(); 1774 } 1775 rope.pull_up_singular_nodes(); 1776 } 1777 1778 // Return the rope 1779 rope 1780 } 1781 RopeSlice(RSEnum::Light { text, .. }) => Rope::from_str(text), 1782 } 1783 } 1784 } 1785 1786 impl From<Rope> for String { 1787 #[inline] from(r: Rope) -> Self1788 fn from(r: Rope) -> Self { 1789 String::from(&r) 1790 } 1791 } 1792 1793 impl<'a> From<&'a Rope> for String { 1794 #[inline] from(r: &'a Rope) -> Self1795 fn from(r: &'a Rope) -> Self { 1796 let mut text = String::with_capacity(r.len_bytes()); 1797 text.extend(r.chunks()); 1798 text 1799 } 1800 } 1801 1802 impl<'a> From<Rope> for std::borrow::Cow<'a, str> { 1803 #[inline] from(r: Rope) -> Self1804 fn from(r: Rope) -> Self { 1805 std::borrow::Cow::Owned(String::from(r)) 1806 } 1807 } 1808 1809 /// Attempts to borrow the contents of the `Rope`, but will convert to an 1810 /// owned string if the contents is not contiguous in memory. 1811 /// 1812 /// Runs in best case O(1), worst case O(N). 1813 impl<'a> From<&'a Rope> for std::borrow::Cow<'a, str> { 1814 #[inline] from(r: &'a Rope) -> Self1815 fn from(r: &'a Rope) -> Self { 1816 if let Node::Leaf(ref text) = *r.root { 1817 std::borrow::Cow::Borrowed(text) 1818 } else { 1819 std::borrow::Cow::Owned(String::from(r)) 1820 } 1821 } 1822 } 1823 1824 impl<'a> FromIterator<&'a str> for Rope { from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = &'a str>,1825 fn from_iter<T>(iter: T) -> Self 1826 where 1827 T: IntoIterator<Item = &'a str>, 1828 { 1829 let mut builder = RopeBuilder::new(); 1830 for chunk in iter { 1831 builder.append(chunk); 1832 } 1833 builder.finish() 1834 } 1835 } 1836 1837 impl<'a> FromIterator<std::borrow::Cow<'a, str>> for Rope { from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = std::borrow::Cow<'a, str>>,1838 fn from_iter<T>(iter: T) -> Self 1839 where 1840 T: IntoIterator<Item = std::borrow::Cow<'a, str>>, 1841 { 1842 let mut builder = RopeBuilder::new(); 1843 for chunk in iter { 1844 builder.append(&chunk); 1845 } 1846 builder.finish() 1847 } 1848 } 1849 1850 impl FromIterator<String> for Rope { from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = String>,1851 fn from_iter<T>(iter: T) -> Self 1852 where 1853 T: IntoIterator<Item = String>, 1854 { 1855 let mut builder = RopeBuilder::new(); 1856 for chunk in iter { 1857 builder.append(&chunk); 1858 } 1859 builder.finish() 1860 } 1861 } 1862 1863 //============================================================== 1864 // Other impls 1865 1866 impl std::fmt::Debug for Rope { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result1867 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 1868 f.debug_list().entries(self.chunks()).finish() 1869 } 1870 } 1871 1872 impl std::fmt::Display for Rope { 1873 #[inline] fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result1874 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 1875 for chunk in self.chunks() { 1876 write!(f, "{}", chunk)? 1877 } 1878 Ok(()) 1879 } 1880 } 1881 1882 impl std::default::Default for Rope { 1883 #[inline] default() -> Self1884 fn default() -> Self { 1885 Self::new() 1886 } 1887 } 1888 1889 impl std::cmp::Eq for Rope {} 1890 1891 impl std::cmp::PartialEq<Rope> for Rope { 1892 #[inline] eq(&self, other: &Rope) -> bool1893 fn eq(&self, other: &Rope) -> bool { 1894 self.slice(..) == other.slice(..) 1895 } 1896 } 1897 1898 impl<'a> std::cmp::PartialEq<&'a str> for Rope { 1899 #[inline] eq(&self, other: &&'a str) -> bool1900 fn eq(&self, other: &&'a str) -> bool { 1901 self.slice(..) == *other 1902 } 1903 } 1904 1905 impl<'a> std::cmp::PartialEq<Rope> for &'a str { 1906 #[inline] eq(&self, other: &Rope) -> bool1907 fn eq(&self, other: &Rope) -> bool { 1908 *self == other.slice(..) 1909 } 1910 } 1911 1912 impl std::cmp::PartialEq<str> for Rope { 1913 #[inline] eq(&self, other: &str) -> bool1914 fn eq(&self, other: &str) -> bool { 1915 self.slice(..) == other 1916 } 1917 } 1918 1919 impl std::cmp::PartialEq<Rope> for str { 1920 #[inline] eq(&self, other: &Rope) -> bool1921 fn eq(&self, other: &Rope) -> bool { 1922 self == other.slice(..) 1923 } 1924 } 1925 1926 impl<'a> std::cmp::PartialEq<String> for Rope { 1927 #[inline] eq(&self, other: &String) -> bool1928 fn eq(&self, other: &String) -> bool { 1929 self.slice(..) == other.as_str() 1930 } 1931 } 1932 1933 impl<'a> std::cmp::PartialEq<Rope> for String { 1934 #[inline] eq(&self, other: &Rope) -> bool1935 fn eq(&self, other: &Rope) -> bool { 1936 self.as_str() == other.slice(..) 1937 } 1938 } 1939 1940 impl<'a> std::cmp::PartialEq<std::borrow::Cow<'a, str>> for Rope { 1941 #[inline] eq(&self, other: &std::borrow::Cow<'a, str>) -> bool1942 fn eq(&self, other: &std::borrow::Cow<'a, str>) -> bool { 1943 self.slice(..) == **other 1944 } 1945 } 1946 1947 impl<'a> std::cmp::PartialEq<Rope> for std::borrow::Cow<'a, str> { 1948 #[inline] eq(&self, other: &Rope) -> bool1949 fn eq(&self, other: &Rope) -> bool { 1950 **self == other.slice(..) 1951 } 1952 } 1953 1954 impl std::cmp::Ord for Rope { 1955 #[inline] cmp(&self, other: &Rope) -> std::cmp::Ordering1956 fn cmp(&self, other: &Rope) -> std::cmp::Ordering { 1957 self.slice(..).cmp(&other.slice(..)) 1958 } 1959 } 1960 1961 impl std::cmp::PartialOrd<Rope> for Rope { 1962 #[inline] partial_cmp(&self, other: &Rope) -> Option<std::cmp::Ordering>1963 fn partial_cmp(&self, other: &Rope) -> Option<std::cmp::Ordering> { 1964 Some(self.cmp(other)) 1965 } 1966 } 1967 1968 //============================================================== 1969 1970 #[cfg(test)] 1971 mod tests { 1972 use super::*; 1973 use crate::str_utils::byte_to_char_idx; 1974 1975 // 127 bytes, 103 chars, 1 line 1976 const TEXT: &str = "Hello there! How're you doing? It's \ 1977 a fine day, isn't it? Aren't you glad \ 1978 we're alive? こんにちは、みんなさん!"; 1979 // 124 bytes, 100 chars, 4 lines 1980 const TEXT_LINES: &str = "Hello there! How're you doing?\nIt's \ 1981 a fine day, isn't it?\nAren't you glad \ 1982 we're alive?\nこんにちは、みんなさん!"; 1983 // 127 bytes, 107 chars, 111 utf16 code units, 1 line 1984 const TEXT_EMOJI: &str = "Hello there! How're you doing? It's \ 1985 a fine day, isn't it? Aren't you glad \ 1986 we're alive? こんにちは、みんなさん!"; 1987 1988 #[test] new_01()1989 fn new_01() { 1990 let r = Rope::new(); 1991 assert_eq!(r, ""); 1992 1993 r.assert_integrity(); 1994 r.assert_invariants(); 1995 } 1996 1997 #[test] from_str()1998 fn from_str() { 1999 let r = Rope::from_str(TEXT); 2000 assert_eq!(r, TEXT); 2001 2002 r.assert_integrity(); 2003 r.assert_invariants(); 2004 } 2005 2006 #[test] len_bytes_01()2007 fn len_bytes_01() { 2008 let r = Rope::from_str(TEXT); 2009 assert_eq!(r.len_bytes(), 127); 2010 } 2011 2012 #[test] len_bytes_02()2013 fn len_bytes_02() { 2014 let r = Rope::from_str(""); 2015 assert_eq!(r.len_bytes(), 0); 2016 } 2017 2018 #[test] len_chars_01()2019 fn len_chars_01() { 2020 let r = Rope::from_str(TEXT); 2021 assert_eq!(r.len_chars(), 103); 2022 } 2023 2024 #[test] len_chars_02()2025 fn len_chars_02() { 2026 let r = Rope::from_str(""); 2027 assert_eq!(r.len_chars(), 0); 2028 } 2029 2030 #[test] len_lines_01()2031 fn len_lines_01() { 2032 let r = Rope::from_str(TEXT_LINES); 2033 assert_eq!(r.len_lines(), 4); 2034 } 2035 2036 #[test] len_lines_02()2037 fn len_lines_02() { 2038 let r = Rope::from_str(""); 2039 assert_eq!(r.len_lines(), 1); 2040 } 2041 2042 #[test] len_utf16_cu_01()2043 fn len_utf16_cu_01() { 2044 let r = Rope::from_str(TEXT); 2045 assert_eq!(r.len_utf16_cu(), 103); 2046 } 2047 2048 #[test] len_utf16_cu_02()2049 fn len_utf16_cu_02() { 2050 let r = Rope::from_str(TEXT_EMOJI); 2051 assert_eq!(r.len_utf16_cu(), 111); 2052 } 2053 2054 #[test] len_utf16_cu_03()2055 fn len_utf16_cu_03() { 2056 let r = Rope::from_str(""); 2057 assert_eq!(r.len_utf16_cu(), 0); 2058 } 2059 2060 #[test] insert_01()2061 fn insert_01() { 2062 let mut r = Rope::from_str(TEXT); 2063 r.insert(3, "AA"); 2064 2065 assert_eq!( 2066 r, 2067 "HelAAlo there! How're you doing? It's \ 2068 a fine day, isn't it? Aren't you glad \ 2069 we're alive? こんにちは、みんなさん!" 2070 ); 2071 2072 r.assert_integrity(); 2073 r.assert_invariants(); 2074 } 2075 2076 #[test] insert_02()2077 fn insert_02() { 2078 let mut r = Rope::from_str(TEXT); 2079 r.insert(0, "AA"); 2080 2081 assert_eq!( 2082 r, 2083 "AAHello there! How're you doing? It's \ 2084 a fine day, isn't it? Aren't you glad \ 2085 we're alive? こんにちは、みんなさん!" 2086 ); 2087 2088 r.assert_integrity(); 2089 r.assert_invariants(); 2090 } 2091 2092 #[test] insert_03()2093 fn insert_03() { 2094 let mut r = Rope::from_str(TEXT); 2095 r.insert(103, "AA"); 2096 2097 assert_eq!( 2098 r, 2099 "Hello there! How're you doing? It's \ 2100 a fine day, isn't it? Aren't you glad \ 2101 we're alive? こんにちは、みんなさん!AA" 2102 ); 2103 2104 r.assert_integrity(); 2105 r.assert_invariants(); 2106 } 2107 2108 #[test] insert_04()2109 fn insert_04() { 2110 let mut r = Rope::new(); 2111 r.insert(0, "He"); 2112 r.insert(2, "l"); 2113 r.insert(3, "l"); 2114 r.insert(4, "o w"); 2115 r.insert(7, "o"); 2116 r.insert(8, "rl"); 2117 r.insert(10, "d!"); 2118 r.insert(3, "zopter"); 2119 2120 assert_eq!("Helzopterlo world!", r); 2121 2122 r.assert_integrity(); 2123 r.assert_invariants(); 2124 } 2125 2126 #[test] insert_05()2127 fn insert_05() { 2128 let mut r = Rope::new(); 2129 r.insert(0, "こんいちは、みんなさん!"); 2130 r.insert(7, "zopter"); 2131 assert_eq!("こんいちは、みzopterんなさん!", r); 2132 2133 r.assert_integrity(); 2134 r.assert_invariants(); 2135 } 2136 2137 #[test] insert_06()2138 fn insert_06() { 2139 let mut r = Rope::new(); 2140 r.insert(0, "こ"); 2141 r.insert(1, "ん"); 2142 r.insert(2, "い"); 2143 r.insert(3, "ち"); 2144 r.insert(4, "は"); 2145 r.insert(5, "、"); 2146 r.insert(6, "み"); 2147 r.insert(7, "ん"); 2148 r.insert(8, "な"); 2149 r.insert(9, "さ"); 2150 r.insert(10, "ん"); 2151 r.insert(11, "!"); 2152 r.insert(7, "zopter"); 2153 assert_eq!("こんいちは、みzopterんなさん!", r); 2154 2155 r.assert_integrity(); 2156 r.assert_invariants(); 2157 } 2158 2159 #[test] insert_char_01()2160 fn insert_char_01() { 2161 let mut r = Rope::from_str(TEXT); 2162 r.insert_char(3, 'A'); 2163 r.insert_char(12, '!'); 2164 r.insert_char(12, '!'); 2165 2166 assert_eq!( 2167 r, 2168 "HelAlo there!!! How're you doing? It's \ 2169 a fine day, isn't it? Aren't you glad \ 2170 we're alive? こんにちは、みんなさん!" 2171 ); 2172 2173 r.assert_integrity(); 2174 r.assert_invariants(); 2175 } 2176 2177 #[test] insert_char_02()2178 fn insert_char_02() { 2179 let mut r = Rope::new(); 2180 2181 r.insert_char(0, '!'); 2182 r.insert_char(0, 'こ'); 2183 r.insert_char(1, 'ん'); 2184 r.insert_char(2, 'い'); 2185 r.insert_char(3, 'ち'); 2186 r.insert_char(4, 'は'); 2187 r.insert_char(5, '、'); 2188 r.insert_char(6, 'み'); 2189 r.insert_char(7, 'ん'); 2190 r.insert_char(8, 'な'); 2191 r.insert_char(9, 'さ'); 2192 r.insert_char(10, 'ん'); 2193 assert_eq!("こんいちは、みんなさん!", r); 2194 2195 r.assert_integrity(); 2196 r.assert_invariants(); 2197 } 2198 2199 #[test] remove_01()2200 fn remove_01() { 2201 let mut r = Rope::from_str(TEXT); 2202 2203 r.remove(5..11); 2204 r.remove(24..31); 2205 r.remove(19..25); 2206 r.remove(75..79); 2207 assert_eq!( 2208 r, 2209 "Hello! How're you \ 2210 a fine day, isn't it? Aren't you glad \ 2211 we're alive? こんにんなさん!" 2212 ); 2213 2214 r.assert_integrity(); 2215 r.assert_invariants(); 2216 } 2217 2218 #[test] remove_02()2219 fn remove_02() { 2220 let mut r = Rope::from_str("\r\n\r\n\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"); 2221 2222 // Make sure CRLF pairs get merged properly, via 2223 // assert_invariants() below. 2224 r.remove(3..6); 2225 assert_eq!(r, "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"); 2226 2227 r.assert_integrity(); 2228 r.assert_invariants(); 2229 } 2230 2231 #[test] remove_03()2232 fn remove_03() { 2233 let mut r = Rope::from_str(TEXT); 2234 2235 // Make sure removing nothing actually does nothing. 2236 r.remove(45..45); 2237 assert_eq!(r, TEXT); 2238 2239 r.assert_integrity(); 2240 r.assert_invariants(); 2241 } 2242 2243 #[test] remove_04()2244 fn remove_04() { 2245 let mut r = Rope::from_str(TEXT); 2246 2247 // Make sure removing everything works. 2248 r.remove(0..103); 2249 assert_eq!(r, ""); 2250 2251 r.assert_integrity(); 2252 r.assert_invariants(); 2253 } 2254 2255 #[test] remove_05()2256 fn remove_05() { 2257 let mut r = Rope::from_str(TEXT); 2258 2259 // Make sure removing a large range works. 2260 r.remove(3..100); 2261 assert_eq!(r, "Helさん!"); 2262 2263 r.assert_integrity(); 2264 r.assert_invariants(); 2265 } 2266 2267 #[test] 2268 #[should_panic] remove_06()2269 fn remove_06() { 2270 let mut r = Rope::from_str(TEXT); 2271 r.remove(56..55); // Wrong ordering of start/end 2272 } 2273 2274 #[test] 2275 #[should_panic] remove_07()2276 fn remove_07() { 2277 let mut r = Rope::from_str(TEXT); 2278 r.remove(102..104); // Removing past the end 2279 } 2280 2281 #[test] 2282 #[should_panic] remove_08()2283 fn remove_08() { 2284 let mut r = Rope::from_str(TEXT); 2285 r.remove(103..104); // Removing past the end 2286 } 2287 2288 #[test] 2289 #[should_panic] remove_09()2290 fn remove_09() { 2291 let mut r = Rope::from_str(TEXT); 2292 r.remove(104..104); // Removing past the end 2293 } 2294 2295 #[test] 2296 #[should_panic] remove_10()2297 fn remove_10() { 2298 let mut r = Rope::from_str(TEXT); 2299 r.remove(104..105); // Removing past the end 2300 } 2301 2302 #[test] split_off_01()2303 fn split_off_01() { 2304 let mut r = Rope::from_str(TEXT); 2305 2306 let r2 = r.split_off(50); 2307 assert_eq!( 2308 r, 2309 "Hello there! How're you doing? It's \ 2310 a fine day, " 2311 ); 2312 assert_eq!( 2313 r2, 2314 "isn't it? Aren't you glad \ 2315 we're alive? こんにちは、みんなさん!" 2316 ); 2317 2318 r.assert_integrity(); 2319 r2.assert_integrity(); 2320 r.assert_invariants(); 2321 r2.assert_invariants(); 2322 } 2323 2324 #[test] split_off_02()2325 fn split_off_02() { 2326 let mut r = Rope::from_str(TEXT); 2327 2328 let r2 = r.split_off(1); 2329 assert_eq!(r, "H"); 2330 assert_eq!( 2331 r2, 2332 "ello there! How're you doing? It's \ 2333 a fine day, isn't it? Aren't you glad \ 2334 we're alive? こんにちは、みんなさん!" 2335 ); 2336 2337 r.assert_integrity(); 2338 r2.assert_integrity(); 2339 r.assert_invariants(); 2340 r2.assert_invariants(); 2341 } 2342 2343 #[test] split_off_03()2344 fn split_off_03() { 2345 let mut r = Rope::from_str(TEXT); 2346 2347 let r2 = r.split_off(102); 2348 assert_eq!( 2349 r, 2350 "Hello there! How're you doing? It's \ 2351 a fine day, isn't it? Aren't you glad \ 2352 we're alive? こんにちは、みんなさん" 2353 ); 2354 assert_eq!(r2, "!"); 2355 2356 r.assert_integrity(); 2357 r2.assert_integrity(); 2358 r.assert_invariants(); 2359 r2.assert_invariants(); 2360 } 2361 2362 #[test] split_off_04()2363 fn split_off_04() { 2364 let mut r = Rope::from_str(TEXT); 2365 2366 let r2 = r.split_off(0); 2367 assert_eq!(r, ""); 2368 assert_eq!( 2369 r2, 2370 "Hello there! How're you doing? It's \ 2371 a fine day, isn't it? Aren't you glad \ 2372 we're alive? こんにちは、みんなさん!" 2373 ); 2374 2375 r.assert_integrity(); 2376 r2.assert_integrity(); 2377 r.assert_invariants(); 2378 r2.assert_invariants(); 2379 } 2380 2381 #[test] split_off_05()2382 fn split_off_05() { 2383 let mut r = Rope::from_str(TEXT); 2384 2385 let r2 = r.split_off(103); 2386 assert_eq!( 2387 r, 2388 "Hello there! How're you doing? It's \ 2389 a fine day, isn't it? Aren't you glad \ 2390 we're alive? こんにちは、みんなさん!" 2391 ); 2392 assert_eq!(r2, ""); 2393 2394 r.assert_integrity(); 2395 r2.assert_integrity(); 2396 r.assert_invariants(); 2397 r2.assert_invariants(); 2398 } 2399 2400 #[test] 2401 #[should_panic] split_off_06()2402 fn split_off_06() { 2403 let mut r = Rope::from_str(TEXT); 2404 r.split_off(104); // One past the end of the rope 2405 } 2406 2407 #[test] append_01()2408 fn append_01() { 2409 let mut r = Rope::from_str( 2410 "Hello there! How're you doing? It's \ 2411 a fine day, isn't ", 2412 ); 2413 let r2 = Rope::from_str( 2414 "it? Aren't you glad \ 2415 we're alive? こんにちは、みんなさん!", 2416 ); 2417 2418 r.append(r2); 2419 assert_eq!(r, TEXT); 2420 2421 r.assert_integrity(); 2422 r.assert_invariants(); 2423 } 2424 2425 #[test] append_02()2426 fn append_02() { 2427 let mut r = Rope::from_str( 2428 "Hello there! How're you doing? It's \ 2429 a fine day, isn't it? Aren't you glad \ 2430 we're alive? こんに", 2431 ); 2432 let r2 = Rope::from_str("ちは、みんなさん!"); 2433 2434 r.append(r2); 2435 assert_eq!(r, TEXT); 2436 2437 r.assert_integrity(); 2438 r.assert_invariants(); 2439 } 2440 2441 #[test] append_03()2442 fn append_03() { 2443 let mut r = Rope::from_str( 2444 "Hello there! How're you doing? It's \ 2445 a fine day, isn't it? Aren't you glad \ 2446 we're alive? こんにちは、みんなさん", 2447 ); 2448 let r2 = Rope::from_str("!"); 2449 2450 r.append(r2); 2451 assert_eq!(r, TEXT); 2452 2453 r.assert_integrity(); 2454 r.assert_invariants(); 2455 } 2456 2457 #[test] append_04()2458 fn append_04() { 2459 let mut r = Rope::from_str("H"); 2460 let r2 = Rope::from_str( 2461 "ello there! How're you doing? It's \ 2462 a fine day, isn't it? Aren't you glad \ 2463 we're alive? こんにちは、みんなさん!", 2464 ); 2465 2466 r.append(r2); 2467 assert_eq!(r, TEXT); 2468 2469 r.assert_integrity(); 2470 r.assert_invariants(); 2471 } 2472 2473 #[test] append_05()2474 fn append_05() { 2475 let mut r = Rope::from_str(TEXT); 2476 let r2 = Rope::from_str(""); 2477 2478 r.append(r2); 2479 assert_eq!(r, TEXT); 2480 2481 r.assert_integrity(); 2482 r.assert_invariants(); 2483 } 2484 2485 #[test] append_06()2486 fn append_06() { 2487 let mut r = Rope::from_str(""); 2488 let r2 = Rope::from_str(TEXT); 2489 2490 r.append(r2); 2491 assert_eq!(r, TEXT); 2492 2493 r.assert_integrity(); 2494 r.assert_invariants(); 2495 } 2496 2497 #[test] append_07()2498 fn append_07() { 2499 let mut r = Rope::from_str("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r"); 2500 let r2 = Rope::from_str("\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r"); 2501 2502 r.append(r2); 2503 assert_eq!(r, "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r"); 2504 assert_eq!(r.len_lines(), 24); 2505 2506 r.assert_integrity(); 2507 r.assert_invariants(); 2508 } 2509 2510 #[test] shrink_to_fit_01()2511 fn shrink_to_fit_01() { 2512 let mut r = Rope::new(); 2513 for _ in 0..10 { 2514 let len = r.len_chars(); 2515 r.insert(len / 2, "こ"); 2516 r.insert(len / 2, "ん"); 2517 r.insert(len / 2, "い"); 2518 r.insert(len / 2, "ち"); 2519 r.insert(len / 2, "は"); 2520 r.insert(len / 2, "、"); 2521 r.insert(len / 2, "み"); 2522 r.insert(len / 2, "ん"); 2523 r.insert(len / 2, "な"); 2524 r.insert(len / 2, "さ"); 2525 r.insert(len / 2, "ん"); 2526 r.insert(len / 2, "!"); 2527 r.insert(len / 2, "zopter"); 2528 } 2529 2530 let r2 = r.clone(); 2531 r.shrink_to_fit(); 2532 2533 assert_eq!(r, r2); 2534 2535 r.assert_integrity(); 2536 r.assert_invariants(); 2537 } 2538 2539 #[test] byte_to_char_01()2540 fn byte_to_char_01() { 2541 let r = Rope::from_str(TEXT); 2542 2543 assert_eq!(0, r.byte_to_char(0)); 2544 assert_eq!(1, r.byte_to_char(1)); 2545 assert_eq!(2, r.byte_to_char(2)); 2546 2547 assert_eq!(91, r.byte_to_char(91)); 2548 assert_eq!(91, r.byte_to_char(92)); 2549 assert_eq!(91, r.byte_to_char(93)); 2550 2551 assert_eq!(92, r.byte_to_char(94)); 2552 assert_eq!(92, r.byte_to_char(95)); 2553 assert_eq!(92, r.byte_to_char(96)); 2554 2555 assert_eq!(102, r.byte_to_char(124)); 2556 assert_eq!(102, r.byte_to_char(125)); 2557 assert_eq!(102, r.byte_to_char(126)); 2558 assert_eq!(103, r.byte_to_char(127)); 2559 } 2560 2561 #[test] byte_to_line_01()2562 fn byte_to_line_01() { 2563 let r = Rope::from_str(TEXT_LINES); 2564 2565 assert_eq!(0, r.byte_to_line(0)); 2566 assert_eq!(0, r.byte_to_line(1)); 2567 2568 assert_eq!(0, r.byte_to_line(31)); 2569 assert_eq!(1, r.byte_to_line(32)); 2570 assert_eq!(1, r.byte_to_line(33)); 2571 2572 assert_eq!(1, r.byte_to_line(58)); 2573 assert_eq!(2, r.byte_to_line(59)); 2574 assert_eq!(2, r.byte_to_line(60)); 2575 2576 assert_eq!(2, r.byte_to_line(87)); 2577 assert_eq!(3, r.byte_to_line(88)); 2578 assert_eq!(3, r.byte_to_line(89)); 2579 assert_eq!(3, r.byte_to_line(124)); 2580 } 2581 2582 #[test] byte_to_line_02()2583 fn byte_to_line_02() { 2584 let r = Rope::from_str(""); 2585 assert_eq!(0, r.byte_to_line(0)); 2586 } 2587 2588 #[test] byte_to_line_03()2589 fn byte_to_line_03() { 2590 let r = Rope::from_str("Hi there\n"); 2591 assert_eq!(0, r.byte_to_line(0)); 2592 assert_eq!(0, r.byte_to_line(8)); 2593 assert_eq!(1, r.byte_to_line(9)); 2594 } 2595 2596 #[test] 2597 #[should_panic] byte_to_line_04()2598 fn byte_to_line_04() { 2599 let r = Rope::from_str(TEXT_LINES); 2600 r.byte_to_line(125); 2601 } 2602 2603 #[test] char_to_byte_01()2604 fn char_to_byte_01() { 2605 let r = Rope::from_str(TEXT); 2606 2607 assert_eq!(0, r.char_to_byte(0)); 2608 assert_eq!(1, r.char_to_byte(1)); 2609 assert_eq!(2, r.char_to_byte(2)); 2610 2611 assert_eq!(91, r.char_to_byte(91)); 2612 assert_eq!(94, r.char_to_byte(92)); 2613 assert_eq!(97, r.char_to_byte(93)); 2614 assert_eq!(100, r.char_to_byte(94)); 2615 2616 assert_eq!(124, r.char_to_byte(102)); 2617 assert_eq!(127, r.char_to_byte(103)); 2618 } 2619 2620 #[test] char_to_line_01()2621 fn char_to_line_01() { 2622 let r = Rope::from_str(TEXT_LINES); 2623 2624 assert_eq!(0, r.char_to_line(0)); 2625 assert_eq!(0, r.char_to_line(1)); 2626 2627 assert_eq!(0, r.char_to_line(31)); 2628 assert_eq!(1, r.char_to_line(32)); 2629 assert_eq!(1, r.char_to_line(33)); 2630 2631 assert_eq!(1, r.char_to_line(58)); 2632 assert_eq!(2, r.char_to_line(59)); 2633 assert_eq!(2, r.char_to_line(60)); 2634 2635 assert_eq!(2, r.char_to_line(87)); 2636 assert_eq!(3, r.char_to_line(88)); 2637 assert_eq!(3, r.char_to_line(89)); 2638 assert_eq!(3, r.char_to_line(100)); 2639 } 2640 2641 #[test] char_to_line_02()2642 fn char_to_line_02() { 2643 let r = Rope::from_str(""); 2644 assert_eq!(0, r.char_to_line(0)); 2645 } 2646 2647 #[test] char_to_line_03()2648 fn char_to_line_03() { 2649 let r = Rope::from_str("Hi there\n"); 2650 assert_eq!(0, r.char_to_line(0)); 2651 assert_eq!(0, r.char_to_line(8)); 2652 assert_eq!(1, r.char_to_line(9)); 2653 } 2654 2655 #[test] 2656 #[should_panic] char_to_line_04()2657 fn char_to_line_04() { 2658 let r = Rope::from_str(TEXT_LINES); 2659 r.char_to_line(101); 2660 } 2661 2662 #[test] line_to_byte_01()2663 fn line_to_byte_01() { 2664 let r = Rope::from_str(TEXT_LINES); 2665 2666 assert_eq!(0, r.line_to_byte(0)); 2667 assert_eq!(32, r.line_to_byte(1)); 2668 assert_eq!(59, r.line_to_byte(2)); 2669 assert_eq!(88, r.line_to_byte(3)); 2670 assert_eq!(124, r.line_to_byte(4)); 2671 } 2672 2673 #[test] line_to_byte_02()2674 fn line_to_byte_02() { 2675 let r = Rope::from_str(""); 2676 assert_eq!(0, r.line_to_byte(0)); 2677 assert_eq!(0, r.line_to_byte(1)); 2678 } 2679 2680 #[test] 2681 #[should_panic] line_to_byte_03()2682 fn line_to_byte_03() { 2683 let r = Rope::from_str(TEXT_LINES); 2684 r.line_to_byte(5); 2685 } 2686 2687 #[test] line_to_char_01()2688 fn line_to_char_01() { 2689 let r = Rope::from_str(TEXT_LINES); 2690 2691 assert_eq!(0, r.line_to_char(0)); 2692 assert_eq!(32, r.line_to_char(1)); 2693 assert_eq!(59, r.line_to_char(2)); 2694 assert_eq!(88, r.line_to_char(3)); 2695 assert_eq!(100, r.line_to_char(4)); 2696 } 2697 2698 #[test] line_to_char_02()2699 fn line_to_char_02() { 2700 let r = Rope::from_str(""); 2701 assert_eq!(0, r.line_to_char(0)); 2702 assert_eq!(0, r.line_to_char(1)); 2703 } 2704 2705 #[test] 2706 #[should_panic] line_to_char_03()2707 fn line_to_char_03() { 2708 let r = Rope::from_str(TEXT_LINES); 2709 r.line_to_char(5); 2710 } 2711 2712 #[test] char_to_utf16_cu_01()2713 fn char_to_utf16_cu_01() { 2714 let r = Rope::from_str(""); 2715 assert_eq!(0, r.char_to_utf16_cu(0)); 2716 } 2717 2718 #[test] 2719 #[should_panic] char_to_utf16_cu_02()2720 fn char_to_utf16_cu_02() { 2721 let r = Rope::from_str(""); 2722 r.char_to_utf16_cu(1); 2723 } 2724 2725 #[test] char_to_utf16_cu_03()2726 fn char_to_utf16_cu_03() { 2727 let r = Rope::from_str(TEXT_EMOJI); 2728 2729 assert_eq!(0, r.char_to_utf16_cu(0)); 2730 2731 assert_eq!(12, r.char_to_utf16_cu(12)); 2732 assert_eq!(14, r.char_to_utf16_cu(13)); 2733 2734 assert_eq!(33, r.char_to_utf16_cu(32)); 2735 assert_eq!(35, r.char_to_utf16_cu(33)); 2736 2737 assert_eq!(63, r.char_to_utf16_cu(61)); 2738 assert_eq!(65, r.char_to_utf16_cu(62)); 2739 2740 assert_eq!(95, r.char_to_utf16_cu(92)); 2741 assert_eq!(97, r.char_to_utf16_cu(93)); 2742 2743 assert_eq!(111, r.char_to_utf16_cu(107)); 2744 } 2745 2746 #[test] 2747 #[should_panic] char_to_utf16_cu_04()2748 fn char_to_utf16_cu_04() { 2749 let r = Rope::from_str(TEXT_EMOJI); 2750 r.char_to_utf16_cu(108); 2751 } 2752 2753 #[test] utf16_cu_to_char_01()2754 fn utf16_cu_to_char_01() { 2755 let r = Rope::from_str(""); 2756 assert_eq!(0, r.utf16_cu_to_char(0)); 2757 } 2758 2759 #[test] 2760 #[should_panic] utf16_cu_to_char_02()2761 fn utf16_cu_to_char_02() { 2762 let r = Rope::from_str(""); 2763 r.utf16_cu_to_char(1); 2764 } 2765 2766 #[test] utf16_cu_to_char_03()2767 fn utf16_cu_to_char_03() { 2768 let r = Rope::from_str(TEXT_EMOJI); 2769 2770 assert_eq!(0, r.utf16_cu_to_char(0)); 2771 2772 assert_eq!(12, r.utf16_cu_to_char(12)); 2773 assert_eq!(12, r.utf16_cu_to_char(13)); 2774 assert_eq!(13, r.utf16_cu_to_char(14)); 2775 2776 assert_eq!(32, r.utf16_cu_to_char(33)); 2777 assert_eq!(32, r.utf16_cu_to_char(34)); 2778 assert_eq!(33, r.utf16_cu_to_char(35)); 2779 2780 assert_eq!(61, r.utf16_cu_to_char(63)); 2781 assert_eq!(61, r.utf16_cu_to_char(64)); 2782 assert_eq!(62, r.utf16_cu_to_char(65)); 2783 2784 assert_eq!(92, r.utf16_cu_to_char(95)); 2785 assert_eq!(92, r.utf16_cu_to_char(96)); 2786 assert_eq!(93, r.utf16_cu_to_char(97)); 2787 2788 assert_eq!(107, r.utf16_cu_to_char(111)); 2789 } 2790 2791 #[test] 2792 #[should_panic] utf16_cu_to_char_04()2793 fn utf16_cu_to_char_04() { 2794 let r = Rope::from_str(TEXT_EMOJI); 2795 r.utf16_cu_to_char(112); 2796 } 2797 2798 #[test] byte_01()2799 fn byte_01() { 2800 let r = Rope::from_str(TEXT); 2801 2802 assert_eq!(r.byte(0), b'H'); 2803 2804 // UTF-8 for "wide exclamation mark" 2805 assert_eq!(r.byte(124), 0xEF); 2806 assert_eq!(r.byte(125), 0xBC); 2807 assert_eq!(r.byte(126), 0x81); 2808 } 2809 2810 #[test] 2811 #[should_panic] byte_02()2812 fn byte_02() { 2813 let r = Rope::from_str(TEXT); 2814 r.byte(127); 2815 } 2816 2817 #[test] 2818 #[should_panic] byte_03()2819 fn byte_03() { 2820 let r = Rope::from_str(""); 2821 r.byte(0); 2822 } 2823 2824 #[test] char_01()2825 fn char_01() { 2826 let r = Rope::from_str(TEXT); 2827 2828 assert_eq!(r.char(0), 'H'); 2829 assert_eq!(r.char(10), 'e'); 2830 assert_eq!(r.char(18), 'r'); 2831 assert_eq!(r.char(102), '!'); 2832 } 2833 2834 #[test] 2835 #[should_panic] char_02()2836 fn char_02() { 2837 let r = Rope::from_str(TEXT); 2838 r.char(103); 2839 } 2840 2841 #[test] 2842 #[should_panic] char_03()2843 fn char_03() { 2844 let r = Rope::from_str(""); 2845 r.char(0); 2846 } 2847 2848 #[test] line_01()2849 fn line_01() { 2850 let r = Rope::from_str(TEXT_LINES); 2851 2852 let l0 = r.line(0); 2853 assert_eq!(l0, "Hello there! How're you doing?\n"); 2854 assert_eq!(l0.len_bytes(), 32); 2855 assert_eq!(l0.len_chars(), 32); 2856 assert_eq!(l0.len_lines(), 2); 2857 2858 let l1 = r.line(1); 2859 assert_eq!(l1, "It's a fine day, isn't it?\n"); 2860 assert_eq!(l1.len_bytes(), 27); 2861 assert_eq!(l1.len_chars(), 27); 2862 assert_eq!(l1.len_lines(), 2); 2863 2864 let l2 = r.line(2); 2865 assert_eq!(l2, "Aren't you glad we're alive?\n"); 2866 assert_eq!(l2.len_bytes(), 29); 2867 assert_eq!(l2.len_chars(), 29); 2868 assert_eq!(l2.len_lines(), 2); 2869 2870 let l3 = r.line(3); 2871 assert_eq!(l3, "こんにちは、みんなさん!"); 2872 assert_eq!(l3.len_bytes(), 36); 2873 assert_eq!(l3.len_chars(), 12); 2874 assert_eq!(l3.len_lines(), 1); 2875 } 2876 2877 #[test] line_02()2878 fn line_02() { 2879 let r = Rope::from_str("Hello there! How're you doing?\n"); 2880 2881 assert_eq!(r.line(0), "Hello there! How're you doing?\n"); 2882 assert_eq!(r.line(1), ""); 2883 } 2884 2885 #[test] line_03()2886 fn line_03() { 2887 let r = Rope::from_str("Hi\nHi\nHi\nHi\nHi\nHi\n"); 2888 2889 assert_eq!(r.line(0), "Hi\n"); 2890 assert_eq!(r.line(1), "Hi\n"); 2891 assert_eq!(r.line(2), "Hi\n"); 2892 assert_eq!(r.line(3), "Hi\n"); 2893 assert_eq!(r.line(4), "Hi\n"); 2894 assert_eq!(r.line(5), "Hi\n"); 2895 assert_eq!(r.line(6), ""); 2896 } 2897 2898 #[test] line_04()2899 fn line_04() { 2900 let r = Rope::from_str(""); 2901 2902 assert_eq!(r.line(0), ""); 2903 } 2904 2905 #[test] 2906 #[should_panic] line_05()2907 fn line_05() { 2908 let r = Rope::from_str(TEXT_LINES); 2909 r.line(4); 2910 } 2911 2912 #[test] line_06()2913 fn line_06() { 2914 let r = Rope::from_str("1\n2\n3\n4\n5\n6\n7\n8"); 2915 2916 assert_eq!(r.line(0).len_lines(), 2); 2917 assert_eq!(r.line(1).len_lines(), 2); 2918 assert_eq!(r.line(2).len_lines(), 2); 2919 assert_eq!(r.line(3).len_lines(), 2); 2920 assert_eq!(r.line(4).len_lines(), 2); 2921 assert_eq!(r.line(5).len_lines(), 2); 2922 assert_eq!(r.line(6).len_lines(), 2); 2923 assert_eq!(r.line(7).len_lines(), 1); 2924 } 2925 2926 #[test] chunk_at_byte()2927 fn chunk_at_byte() { 2928 let r = Rope::from_str(TEXT_LINES); 2929 let mut t = TEXT_LINES; 2930 2931 let mut last_chunk = ""; 2932 for i in 0..r.len_bytes() { 2933 let (chunk, b, c, l) = r.chunk_at_byte(i); 2934 assert_eq!(c, byte_to_char_idx(TEXT_LINES, b)); 2935 assert_eq!(l, byte_to_line_idx(TEXT_LINES, b)); 2936 if chunk != last_chunk { 2937 assert_eq!(chunk, &t[..chunk.len()]); 2938 t = &t[chunk.len()..]; 2939 last_chunk = chunk; 2940 } 2941 2942 let c1 = { 2943 let i2 = byte_to_char_idx(TEXT_LINES, i); 2944 TEXT_LINES.chars().nth(i2).unwrap() 2945 }; 2946 let c2 = { 2947 let i2 = i - b; 2948 let i3 = byte_to_char_idx(chunk, i2); 2949 chunk.chars().nth(i3).unwrap() 2950 }; 2951 assert_eq!(c1, c2); 2952 } 2953 assert_eq!(t.len(), 0); 2954 } 2955 2956 #[test] chunk_at_char()2957 fn chunk_at_char() { 2958 let r = Rope::from_str(TEXT_LINES); 2959 let mut t = TEXT_LINES; 2960 2961 let mut last_chunk = ""; 2962 for i in 0..r.len_chars() { 2963 let (chunk, b, c, l) = r.chunk_at_char(i); 2964 assert_eq!(b, char_to_byte_idx(TEXT_LINES, c)); 2965 assert_eq!(l, char_to_line_idx(TEXT_LINES, c)); 2966 if chunk != last_chunk { 2967 assert_eq!(chunk, &t[..chunk.len()]); 2968 t = &t[chunk.len()..]; 2969 last_chunk = chunk; 2970 } 2971 2972 let c1 = TEXT_LINES.chars().nth(i).unwrap(); 2973 let c2 = { 2974 let i2 = i - c; 2975 chunk.chars().nth(i2).unwrap() 2976 }; 2977 assert_eq!(c1, c2); 2978 } 2979 assert_eq!(t.len(), 0); 2980 } 2981 2982 #[test] chunk_at_line_break()2983 fn chunk_at_line_break() { 2984 let r = Rope::from_str(TEXT_LINES); 2985 2986 // First chunk 2987 { 2988 let (chunk, b, c, l) = r.chunk_at_line_break(0); 2989 assert_eq!(chunk, &TEXT_LINES[..chunk.len()]); 2990 assert_eq!(b, 0); 2991 assert_eq!(c, 0); 2992 assert_eq!(l, 0); 2993 } 2994 2995 // Middle chunks 2996 for i in 1..r.len_lines() { 2997 let (chunk, b, c, l) = r.chunk_at_line_break(i); 2998 assert_eq!(chunk, &TEXT_LINES[b..(b + chunk.len())]); 2999 assert_eq!(c, byte_to_char_idx(TEXT_LINES, b)); 3000 assert_eq!(l, byte_to_line_idx(TEXT_LINES, b)); 3001 assert!(l < i); 3002 assert!(i <= byte_to_line_idx(TEXT_LINES, b + chunk.len())); 3003 } 3004 3005 // Last chunk 3006 { 3007 let (chunk, b, c, l) = r.chunk_at_line_break(r.len_lines()); 3008 assert_eq!(chunk, &TEXT_LINES[(TEXT_LINES.len() - chunk.len())..]); 3009 assert_eq!(chunk, &TEXT_LINES[b..]); 3010 assert_eq!(c, byte_to_char_idx(TEXT_LINES, b)); 3011 assert_eq!(l, byte_to_line_idx(TEXT_LINES, b)); 3012 } 3013 } 3014 3015 #[test] slice_01()3016 fn slice_01() { 3017 let r = Rope::from_str(TEXT); 3018 3019 let s = r.slice(0..r.len_chars()); 3020 3021 assert_eq!(TEXT, s); 3022 } 3023 3024 #[test] slice_02()3025 fn slice_02() { 3026 let r = Rope::from_str(TEXT); 3027 3028 let s = r.slice(5..21); 3029 3030 assert_eq!(&TEXT[5..21], s); 3031 } 3032 3033 #[test] slice_03()3034 fn slice_03() { 3035 let r = Rope::from_str(TEXT); 3036 3037 let s = r.slice(31..97); 3038 3039 assert_eq!(&TEXT[31..109], s); 3040 } 3041 3042 #[test] slice_04()3043 fn slice_04() { 3044 let r = Rope::from_str(TEXT); 3045 3046 let s = r.slice(53..53); 3047 3048 assert_eq!("", s); 3049 } 3050 3051 #[test] 3052 #[should_panic] slice_05()3053 fn slice_05() { 3054 let r = Rope::from_str(TEXT); 3055 r.slice(53..52); 3056 } 3057 3058 #[test] 3059 #[should_panic] slice_06()3060 fn slice_06() { 3061 let r = Rope::from_str(TEXT); 3062 r.slice(102..104); 3063 } 3064 3065 #[test] eq_rope_01()3066 fn eq_rope_01() { 3067 let r = Rope::from_str(""); 3068 3069 assert_eq!(r, r); 3070 } 3071 3072 #[test] eq_rope_02()3073 fn eq_rope_02() { 3074 let r = Rope::from_str(TEXT); 3075 3076 assert_eq!(r, r); 3077 } 3078 3079 #[test] eq_rope_03()3080 fn eq_rope_03() { 3081 let r1 = Rope::from_str(TEXT); 3082 let mut r2 = r1.clone(); 3083 r2.remove(26..27); 3084 r2.insert(26, "z"); 3085 3086 assert_ne!(r1, r2); 3087 } 3088 3089 #[test] eq_rope_04()3090 fn eq_rope_04() { 3091 let r = Rope::from_str(""); 3092 3093 assert_eq!(r, ""); 3094 assert_eq!("", r); 3095 } 3096 3097 #[test] eq_rope_05()3098 fn eq_rope_05() { 3099 let r = Rope::from_str(TEXT); 3100 3101 assert_eq!(r, TEXT); 3102 assert_eq!(TEXT, r); 3103 } 3104 3105 #[test] eq_rope_06()3106 fn eq_rope_06() { 3107 let mut r = Rope::from_str(TEXT); 3108 r.remove(26..27); 3109 r.insert(26, "z"); 3110 3111 assert_ne!(r, TEXT); 3112 assert_ne!(TEXT, r); 3113 } 3114 3115 #[test] eq_rope_07()3116 fn eq_rope_07() { 3117 let r = Rope::from_str(TEXT); 3118 let s: String = TEXT.into(); 3119 3120 assert_eq!(r, s); 3121 assert_eq!(s, r); 3122 } 3123 3124 #[test] to_string_01()3125 fn to_string_01() { 3126 let r = Rope::from_str(TEXT); 3127 let s: String = (&r).into(); 3128 3129 assert_eq!(r, s); 3130 } 3131 3132 #[test] to_cow_01()3133 fn to_cow_01() { 3134 use std::borrow::Cow; 3135 let r = Rope::from_str(TEXT); 3136 let cow: Cow<str> = (&r).into(); 3137 3138 assert_eq!(r, cow); 3139 } 3140 3141 #[test] to_cow_02()3142 fn to_cow_02() { 3143 use std::borrow::Cow; 3144 let r = Rope::from_str(TEXT); 3145 let cow: Cow<str> = (r.clone()).into(); 3146 3147 assert_eq!(r, cow); 3148 } 3149 3150 #[test] to_cow_03()3151 fn to_cow_03() { 3152 use std::borrow::Cow; 3153 let r = Rope::from_str("a"); 3154 let cow: Cow<str> = (&r).into(); 3155 3156 // Make sure it's borrowed. 3157 if let Cow::Owned(_) = cow { 3158 panic!("Small Cow conversions should result in a borrow."); 3159 } 3160 3161 assert_eq!(r, cow); 3162 } 3163 3164 #[test] from_rope_slice_01()3165 fn from_rope_slice_01() { 3166 let r1 = Rope::from_str(TEXT); 3167 let s = r1.slice(..); 3168 let r2: Rope = s.into(); 3169 3170 assert_eq!(r1, r2); 3171 assert_eq!(s, r2); 3172 } 3173 3174 #[test] from_rope_slice_02()3175 fn from_rope_slice_02() { 3176 let r1 = Rope::from_str(TEXT); 3177 let s = r1.slice(0..24); 3178 let r2: Rope = s.into(); 3179 3180 assert_eq!(s, r2); 3181 } 3182 3183 #[test] from_rope_slice_03()3184 fn from_rope_slice_03() { 3185 let r1 = Rope::from_str(TEXT); 3186 let s = r1.slice(13..89); 3187 let r2: Rope = s.into(); 3188 3189 assert_eq!(s, r2); 3190 } 3191 3192 #[test] from_rope_slice_04()3193 fn from_rope_slice_04() { 3194 let r1 = Rope::from_str(TEXT); 3195 let s = r1.slice(13..41); 3196 let r2: Rope = s.into(); 3197 3198 assert_eq!(s, r2); 3199 } 3200 3201 #[test] from_iter_01()3202 fn from_iter_01() { 3203 let r1 = Rope::from_str(TEXT); 3204 let r2: Rope = Rope::from_iter(r1.chunks()); 3205 3206 assert_eq!(r1, r2); 3207 } 3208 3209 // Iterator tests are in the iter module 3210 } 3211