@ -120,6 +120,43 @@ pub fn nth_next_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -
chunk_char_idx + tmp
chunk_char_idx + tmp
}
}
#[ must_use ]
pub fn nth_next_grapheme_boundary_byte ( slice : RopeSlice , mut byte_idx : usize , n : usize ) -> usize {
// Bounds check
debug_assert! ( byte_idx < = slice . len_bytes ( ) ) ;
// Get the chunk with our byte index in it.
let ( mut chunk , mut chunk_byte_idx , mut _chunk_char_idx , _ ) = slice . chunk_at_byte ( byte_idx ) ;
// Set up the grapheme cursor.
let mut gc = GraphemeCursor ::new ( byte_idx , slice . len_bytes ( ) , true ) ;
// Find the nth next grapheme cluster boundary.
for _ in 0 .. n {
loop {
match gc . next_boundary ( chunk , chunk_byte_idx ) {
Ok ( None ) = > return slice . len_bytes ( ) ,
Ok ( Some ( n ) ) = > {
byte_idx = n ;
break ;
}
Err ( GraphemeIncomplete ::NextChunk ) = > {
chunk_byte_idx + = chunk . len ( ) ;
let ( a , _ , _c , _ ) = slice . chunk_at_byte ( chunk_byte_idx ) ;
chunk = a ;
// chunk_char_idx = c;
}
Err ( GraphemeIncomplete ::PreContext ( n ) ) = > {
let ctx_chunk = slice . chunk_at_byte ( n - 1 ) . 0 ;
gc . provide_context ( ctx_chunk , n - ctx_chunk . len ( ) ) ;
}
_ = > unreachable! ( ) ,
}
}
}
byte_idx
}
/// Finds the next grapheme boundary after the given char position.
/// Finds the next grapheme boundary after the given char position.
#[ must_use ]
#[ must_use ]
#[ inline(always) ]
#[ inline(always) ]
@ -127,6 +164,13 @@ pub fn next_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
nth_next_grapheme_boundary ( slice , char_idx , 1 )
nth_next_grapheme_boundary ( slice , char_idx , 1 )
}
}
/// Finds the next grapheme boundary after the given byte position.
#[ must_use ]
#[ inline(always) ]
pub fn next_grapheme_boundary_byte ( slice : RopeSlice , byte_idx : usize ) -> usize {
nth_next_grapheme_boundary_byte ( slice , byte_idx , 1 )
}
/// Returns the passed char index if it's already a grapheme boundary,
/// Returns the passed char index if it's already a grapheme boundary,
/// or the next grapheme boundary char index if not.
/// or the next grapheme boundary char index if not.
#[ must_use ]
#[ must_use ]
@ -151,6 +195,18 @@ pub fn ensure_grapheme_boundary_prev(slice: RopeSlice, char_idx: usize) -> usize
}
}
}
}
/// Returns the passed byte index if it's already a grapheme boundary,
/// or the next grapheme boundary byte index if not.
#[ must_use ]
#[ inline ]
pub fn ensure_grapheme_boundary_next_byte ( slice : RopeSlice , byte_idx : usize ) -> usize {
if byte_idx = = 0 {
byte_idx
} else {
next_grapheme_boundary_byte ( slice , byte_idx - 1 )
}
}
/// Returns whether the given char position is a grapheme boundary.
/// Returns whether the given char position is a grapheme boundary.
#[ must_use ]
#[ must_use ]
pub fn is_grapheme_boundary ( slice : RopeSlice , char_idx : usize ) -> bool {
pub fn is_grapheme_boundary ( slice : RopeSlice , char_idx : usize ) -> bool {