@@ -605,23 +605,76 @@ private bool CopyMatchFromWindow(
605605 src += _windowSize ;
606606 }
607607
608- for ( int i = 0 ; i < matchLength ; i ++ )
608+ while ( matchLength > 0 )
609609 {
610- byte value = _window [ src ] ;
610+ // How much can we read contiguously from current source position
611+ // before wrapping the circular window?
612+ int srcRun = _windowSize - src ;
611613
612- if ( ( uint ) dstPos < ( uint ) output . Length )
614+ // How much can we write contiguously to current window position
615+ // before wrapping the circular window?
616+ int dstRun = _windowSize - _windowPos ;
617+
618+ int chunk = Math . Min ( matchLength , Math . Min ( srcRun , dstRun ) ) ;
619+
620+ // If source and destination are safely separated inside the current
621+ // contiguous chunk, we can copy the whole chunk with Span.CopyTo.
622+ // Otherwise fall back to byte-serial copying to preserve overlap behavior.
623+ if ( chunk > 0 && ( src + chunk <= _windowPos || _windowPos + chunk <= src ) )
613624 {
614- output [ dstPos ] = value ;
615- }
625+ var srcSlice = _window . Slice ( src , chunk ) ;
626+ var dstSlice = _window . Slice ( _windowPos , chunk ) ;
627+
628+ srcSlice . CopyTo ( dstSlice ) ;
629+
630+ int outChunk = Math . Min ( chunk , output . Length - dstPos ) ;
631+ if ( outChunk > 0 )
632+ {
633+ dstSlice . Slice ( 0 , outChunk ) . CopyTo ( output . Slice ( dstPos , outChunk ) ) ;
634+ }
616635
617- dstPos ++ ;
618- blockRemaining -- ;
619- WriteWindowByte ( value ) ;
636+ dstPos += chunk ;
637+ blockRemaining -= chunk ;
638+ matchLength -= chunk ;
620639
621- src ++ ;
622- if ( src == _windowSize )
640+ _windowPos += chunk ;
641+ if ( _windowPos == _windowSize )
642+ {
643+ _windowPos = 0 ;
644+ }
645+
646+ src += chunk ;
647+ if ( src == _windowSize )
648+ {
649+ src = 0 ;
650+ }
651+ }
652+ else
623653 {
624- src = 0 ;
654+ byte value = _window [ src ] ;
655+
656+ if ( ( uint ) dstPos < ( uint ) output . Length )
657+ {
658+ output [ dstPos ] = value ;
659+ }
660+
661+ _window [ _windowPos ] = value ;
662+
663+ dstPos ++ ;
664+ blockRemaining -- ;
665+ matchLength -- ;
666+
667+ src ++ ;
668+ if ( src == _windowSize )
669+ {
670+ src = 0 ;
671+ }
672+
673+ _windowPos ++ ;
674+ if ( _windowPos == _windowSize )
675+ {
676+ _windowPos = 0 ;
677+ }
625678 }
626679 }
627680
0 commit comments