@@ -360,7 +360,10 @@ impl GraphemeCursor {
360360match self . state {
361361GraphemeState :: Regional =>self . handle_regional ( chunk, chunk_start) ,
362362GraphemeState :: Emoji =>self . handle_emoji ( chunk, chunk_start) ,
363- _ =>panic ! ( "invalid state" )
363+ _ =>if self . cat_before . is_none ( ) &&self . offset == chunk. len ( ) + chunk_start{
364+ let ch = chunk. chars ( ) . rev ( ) . next ( ) . unwrap ( ) ;
365+ self . cat_before =Some ( gr:: grapheme_category ( ch) ) ;
366+ } ,
364367}
365368}
366369
@@ -406,6 +409,7 @@ impl GraphemeCursor {
406409return ;
407410}
408411self . pre_context_offset =Some ( chunk_start) ;
412+ self . state =GraphemeState :: Regional ;
409413}
410414
411415fn handle_emoji ( & mut self , chunk : & str , chunk_start : usize ) {
@@ -428,6 +432,7 @@ impl GraphemeCursor {
428432return ;
429433}
430434self . pre_context_offset =Some ( chunk_start) ;
435+ self . state =GraphemeState :: Emoji ;
431436}
432437
433438/// Determine whether the current cursor location is a grapheme cluster boundary.
@@ -659,3 +664,21 @@ impl GraphemeCursor {
659664}
660665}
661666}
667+
668+ #[ test]
669+ fn test_grapheme_cursor_ris_precontext ( ) {
670+ let s ="\u{1f1fa} \u{1f1f8} \u{1f1fa} \u{1f1f8} \u{1f1fa} \u{1f1f8} " ;
671+ let mut c =GraphemeCursor :: new ( 8 , s. len ( ) , true ) ;
672+ assert_eq ! ( c. is_boundary( & s[ 4 ..] , 4 ) , Err ( GraphemeIncomplete :: PreContext ( 4 ) ) ) ;
673+ c. provide_context ( & s[ ..4 ] , 0 ) ;
674+ assert_eq ! ( c. is_boundary( & s[ 4 ..] , 4 ) , Ok ( true ) ) ;
675+ }
676+
677+ #[ test]
678+ fn test_grapheme_cursor_chunk_start_require_precontext ( ) {
679+ let s ="\r \n " ;
680+ let mut c =GraphemeCursor :: new ( 1 , s. len ( ) , true ) ;
681+ assert_eq ! ( c. is_boundary( & s[ 1 ..] , 1 ) , Err ( GraphemeIncomplete :: PreContext ( 1 ) ) ) ;
682+ c. provide_context ( & s[ ..1 ] , 0 ) ;
683+ assert_eq ! ( c. is_boundary( & s[ 1 ..] , 1 ) , Ok ( false ) ) ;
684+ }