@ -1,11 +1,53 @@
//! Deltas and applying them
use super ::* ;
use difference ::{
Changeset ,
Difference ,
} ;
const MAX_SINGLE_DELTA_SIZE : usize = 14 ;
const DELTA_BREAK : & str = "" ;
/// Infer all deltas needed to be sequentially applied to `orig` to transform it to `new`, return the number inserted into `output`.
pub fn infer_deltas < T : BackInserter < Delta > + ? Sized > ( output : & mut T , orig : & str , new : & str ) -> usize
{
let set = Changeset ::new ( orig , new , DELTA_BREAK ) ;
let mut done = 0 ;
let mut position = 0 ;
for diff in set . diffs . into_iter ( ) {
match diff {
Difference ::Same ( string ) = > {
position + = string . len ( ) ;
} ,
Difference ::Rem ( string ) = > {
output . push_back ( Delta {
location : position ,
kind : DeltaKind ::RemoveAhead { span_len : string . len ( ) } ,
} ) ;
done + = 1 ;
} ,
Difference ::Add ( string ) = > {
let mut passer = BackInsertPass ::new ( | ( span , span_len ) | {
output . push_back ( Delta {
location : position ,
kind : DeltaKind ::Insert {
span , span_len ,
} ,
} ) ;
position + = usize ::from ( span_len ) ;
done + = 1 ;
} ) ;
delta_span_many ( & mut passer , string . chars ( ) ) ;
} ,
}
}
done
}
/// Create a delta span from an input iterator.
///
/// This function can take no more than 255 chars from the input. The number of chars inserted is also returned as `u8`.
/// This function can take no more than `min( 255, MAX_SINGLE_DELTA_SIZE)` chars from the input. The number of chars inserted is also returned as `u8`.
pub ( super ) fn delta_span < I > ( from : I ) -> ( [ char ; MAX_SINGLE_DELTA_SIZE ] , u8 )
where I : IntoIterator < Item = char >
{
@ -21,11 +63,29 @@ where I: IntoIterator<Item = char>
( output , sz )
}
/// Create as many delta spans needed from an input iterator.
///
/// This function can take as many inputs as needed, and outputs the needed amount of spans into `into`, and then returns the number added.
pub ( super ) fn delta_span_many < T : BackInserter < ( [ char ; MAX_SINGLE_DELTA_SIZE ] , u8 ) > + ? Sized , I > ( into : & mut T , from : I ) -> usize
where I : IntoIterator < Item = char >
{
let mut iter = from . into_iter ( ) ;
let mut added = 0 ;
loop {
match delta_span ( & mut iter ) {
( _ , 0 ) = > break ,
other = > into . push_back ( other ) ,
}
added + = 1 ;
}
added
}
/// Information about the delta to be applied in `Delta`.
#[ derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash) ]
pub enum DeltaKind
{
/// Append to the end of body. Equivilant to `Insert` with a location at `karada.scape.len()` (the end of the buffer). Might be removed idk
/// Append to the end of body. Equivilant to `Insert` with a location at `karada.scape.len()` (the end of the buffer).
Append {
span : [ char ; MAX_SINGLE_DELTA_SIZE ] ,
span_len : u8 ,
@ -35,14 +95,18 @@ pub enum DeltaKind
span : [ char ; MAX_SINGLE_DELTA_SIZE ] ,
span_len : u8 ,
} ,
/// Remove `span_len` chars ahead of `location`. (INCLUSIVE)
/// Remove `span_len` chars from `location`.
RemoveAhead {
span_len : usize ,
} ,
/// Remove `span_len` chars behind this `location`. (EXCLUSIVE)
/// Remove `span_len` chars up to but not including `location`.
RemoveBehind {
span_len : usize ,
} ,
/// Remove everything from `location` to the end.
Truncate ,
/// Remove everything from 0 to `location`.
Shift ,
/// Remove char at `location`
RemoveSingle ,
/// Remove entire post body
@ -57,7 +121,7 @@ pub struct Delta
///
/// Insertions off the end of the buffer are to be appened instead.
location : usize ,
/// The kind of delta t oinsert
/// The kind of delta t o insert
kind : DeltaKind ,
}
@ -80,16 +144,21 @@ impl Delta
inserter . insert ( self . location , span [ 0 ] ) ;
} else if span . len ( ) > 1 {
inserter . insert_exact ( self . location , span . iter ( ) . copied ( ) ) ;
/* / / reserve the extra space
inserter . reserve ( span . len ( ) ) ;
// shift everything across, replacing with the new values
let splice : Vec < _ > = inserter . splice ( self . location .. , span . iter ( ) . cloned ( ) ) . collect ( ) ;
// add tail back
inserter . extend ( splice ) ; * /
}
} ,
_ = > unimplemented! ( ) ,
DeltaKind ::RemoveAhead { span_len } = > {
inserter . drain ( self . location .. ( self . location + span_len ) ) ;
} ,
DeltaKind ::RemoveBehind { span_len } = > {
let span_st = self . location . checked_sub ( span_len ) . unwrap_or ( 0 ) ;
inserter . drain ( span_st .. self . location ) ;
} ,
DeltaKind ::RemoveSingle = > {
inserter . remove ( self . location ) ;
} ,
DeltaKind ::Clear = > inserter . clear ( ) ,
DeltaKind ::Truncate = > inserter . truncate ( self . location ) ,
DeltaKind ::Shift = > ( ( ) , inserter . drain ( .. self . location ) ) . 0 ,
}
}
}
@ -99,6 +168,27 @@ mod tests
{
use super ::* ;
#[ test ]
fn infer_and_insert ( )
{
let orig = "the quick brown fox jumped over the lazy dog !!!!" ;
let new = "the quick brown dog jumped over the lazy fox twice" ;
let mut deltas = Vec ::new ( ) ;
infer_deltas ( & mut deltas , orig , new ) ;
println! ( "{:#?}" , deltas ) ;
let output : String = {
let mut scape : Vec < _ > = orig . chars ( ) . collect ( ) ;
for delta in deltas . into_iter ( ) {
delta . insert ( & mut scape ) ;
}
scape . into_iter ( ) . collect ( )
} ;
assert_eq! ( & output [ .. ] , & new [ .. ] ) ;
}
macro_rules! insert {
( $expects :literal ; $start :literal , $ins :literal , $where :expr ) = > {
{