pub fn remove_char_range(
        &mut self,
        start_idx: usize,
        end_idx: usize,
        node_info: TextInfo,
    ) -> (TextInfo, bool, bool) {
        if start_idx == end_idx {
            return (node_info, false, false);
        }

        match *self {
            // If it's a leaf
            Node::Leaf(ref mut leaf_text) => {
                let byte_start = char_to_byte_idx(leaf_text, start_idx);
                let byte_end =
                    byte_start + char_to_byte_idx(&leaf_text[byte_start..], end_idx - start_idx);

                // Remove text and calculate new info & seam info
                if byte_start > 0 || byte_end < leaf_text.len() {
                    let seam = (byte_start == 0 && leaf_text.as_bytes()[byte_end] == 0x0A)
                        || (byte_end == leaf_text.len()
                            && leaf_text.as_bytes()[byte_start - 1] == 0x0D);

                    let seg_len = byte_end - byte_start; // Length of removal segement
                    if seg_len < (leaf_text.len() - seg_len) {
                        let mut info =
                            node_info - TextInfo::from_str(&leaf_text[byte_start..byte_end]);

                        // Check for CRLF pairs on the removal seams, and
                        // adjust line break counts accordingly.
                        if byte_end < leaf_text.len()
                            && leaf_text.as_bytes()[byte_end - 1] == 0x0D
                            && leaf_text.as_bytes()[byte_end] == 0x0A
                        {
                            info.line_breaks += 1;
                        }
                        if byte_start > 0 && leaf_text.as_bytes()[byte_start - 1] == 0x0D {
                            if leaf_text.as_bytes()[byte_start] == 0x0A {
                                info.line_breaks += 1;
                            }

                            if byte_end < leaf_text.len() && leaf_text.as_bytes()[byte_end] == 0x0A
                            {
                                info.line_breaks -= 1;
                            }
                        }

                        // Remove the text
                        leaf_text.remove_range(byte_start, byte_end);

                        (info, seam, false)
                    } else {
                        // Remove the text
                        leaf_text.remove_range(byte_start, byte_end);

                        (TextInfo::from_str(&leaf_text), seam, false)
                    }
                } else {
                    // Remove all of the text
                    leaf_text.remove_range(byte_start, byte_end);

                    (TextInfo::new(), true, false)
                }
            }

            // If it's internal, it's much more complicated
            Node::Internal(ref mut children) => {
                // Shared code for handling children.
                // Returns (in this order):
                // - Whether there's a possible CRLF seam that needs fixing.
                // - Whether the tree may need invariant fixing.
                // - Updated TextInfo of the node.
                let handle_child = |children: &mut NodeChildren,
                                    child_i: usize,
                                    c_char_acc: usize|
                 -> (bool, bool, TextInfo) {
                    // Recurse into child
                    let tmp_info = children.info()[child_i];
                    let tmp_chars = children.info()[child_i].chars as usize;
                    let (new_info, seam, needs_fix) =
                        Arc::make_mut(&mut children.nodes_mut()[child_i]).remove_char_range(
                            start_idx - c_char_acc.min(start_idx),
                            (end_idx - c_char_acc).min(tmp_chars),
                            tmp_info,
                        );

                    // Handle result
                    if new_info.bytes == 0 {
                        children.remove(child_i);
                    } else {
                        children.info_mut()[child_i] = new_info;
                    }

                    (seam, needs_fix, new_info)
                };

                // Shared code for merging children
                let merge_child = |children: &mut NodeChildren, child_i: usize| {
                    if child_i < children.len()
                        && children.len() > 1
                        && children.nodes()[child_i].is_undersized()
                    {
                        if child_i == 0 {
                            children.merge_distribute(child_i, child_i + 1);
                        } else {
                            children.merge_distribute(child_i - 1, child_i);
                        }
                    }
                };

                // Get child info for the two char indices
                let ((l_child_i, l_char_acc), (r_child_i, r_char_acc)) =
                    children.search_char_idx_range(start_idx, end_idx);

                // Both indices point into the same child
                if l_child_i == r_child_i {
                    let info = children.info()[l_child_i];
                    let (seam, mut needs_fix, new_info) =
                        handle_child(children, l_child_i, l_char_acc);

                    if children.len() > 0 {
                        merge_child(children, l_child_i);

                        // If we couldn't get all children >= minimum size, then
                        // we'll need to fix that later.
                        if children.nodes()[l_child_i.min(children.len() - 1)].is_undersized() {
                            needs_fix = true;
                        }
                    }

                    return (node_info - info + new_info, seam, needs_fix);
                }
                // We're dealing with more than one child.
                else {
                    let mut needs_fix = false;

                    // Calculate the start..end range of nodes to be removed.
                    let r_child_exists: bool;
                    let start_i = l_child_i + 1;
                    let end_i = if r_char_acc + children.info()[r_child_i].chars as usize == end_idx
                    {
                        r_child_exists = false;
                        r_child_i + 1
                    } else {
                        r_child_exists = true;
                        r_child_i
                    };

                    // Remove the children
                    for _ in start_i..end_i {
                        children.remove(start_i);
                    }

                    // Handle right child
                    if r_child_exists {
                        let (_, fix, _) = handle_child(children, l_child_i + 1, r_char_acc);
                        needs_fix |= fix;
                    }

                    // Handle left child
                    let (seam, fix, _) = handle_child(children, l_child_i, l_char_acc);
                    needs_fix |= fix;

                    if children.len() > 0 {
                        // Handle merging
                        let merge_extent = 1 + if r_child_exists { 1 } else { 0 };
                        for i in (l_child_i..(l_child_i + merge_extent)).rev() {
                            merge_child(children, i);
                        }

                        // If we couldn't get all children >= minimum size, then
                        // we'll need to fix that later.
                        if children.nodes()[l_child_i.min(children.len() - 1)].is_undersized() {
                            needs_fix = true;
                        }
                    }

                    // Return
                    return (children.combined_info(), seam, needs_fix);
                }
            }
        }
    }
/// Removes chars in the range `start_idx..end_idx`.
///
/// Returns (in this order):
/// - The updated TextInfo for the node.
/// - Whether there's a possible CRLF seam that needs fixing.
/// - Whether fix_tree_seam() needs to be run after this.
///
/// WARNING: does not correctly handle all text being removed.  That
/// should be special-cased in calling code.


does not correctly handle all text being removed.  That
should be special-cased in calling code.
does not correctly handle all text being removed . That should be special - cased in calling code .
pub fn remove_char_range(
        &mut self,
        start_idx: usize,
        end_idx: usize,
        node_info: TextInfo,
    ) -> (TextInfo, bool, bool) {
        if start_idx == end_idx {
            return (node_info, false, false);
        }
        match *self {
            // If it's a leaf
            Node::Leaf(ref mut leaf_text) => {
                let byte_start = char_to_byte_idx(leaf_text, start_idx);
                let byte_end =
                    byte_start + char_to_byte_idx(&leaf_text[byte_start..], end_idx - start_idx);
                // Remove text and calculate new info & seam info
                if byte_start > 0 || byte_end < leaf_text.len() {
                    let seam = (byte_start == 0 && leaf_text.as_bytes()[byte_end] == 0x0A)
                        || (byte_end == leaf_text.len()
                            && leaf_text.as_bytes()[byte_start - 1] == 0x0D);
                    let seg_len = byte_end - byte_start; // Length of removal segement
                    if seg_len < (leaf_text.len() - seg_len) {
                        let mut info =
                            node_info - TextInfo::from_str(&leaf_text[byte_start..byte_end]);
                        // Check for CRLF pairs on the removal seams, and
                        // adjust line break counts accordingly.
                        if byte_end < leaf_text.len()
                            && leaf_text.as_bytes()[byte_end - 1] == 0x0D
                            && leaf_text.as_bytes()[byte_end] == 0x0A
                        {
                            info.line_breaks += 1;
                        }
                        if byte_start > 0 && leaf_text.as_bytes()[byte_start - 1] == 0x0D {
                            if leaf_text.as_bytes()[byte_start] == 0x0A {
                                info.line_breaks += 1;
                            }
                            if byte_end < leaf_text.len() && leaf_text.as_bytes()[byte_end] == 0x0A
                            {
                                info.line_breaks -= 1;
                            }
                        }
                        // Remove the text
                        leaf_text.remove_range(byte_start, byte_end);
                        (info, seam, false)
                    } else {
                        // Remove the text
                        leaf_text.remove_range(byte_start, byte_end);
                        (TextInfo::from_str(&leaf_text), seam, false)
                    }
                } else {
                    // Remove all of the text
                    leaf_text.remove_range(byte_start, byte_end);
                    (TextInfo::new(), true, false)
                }
            }
            // If it's internal, it's much more complicated
            Node::Internal(ref mut children) => {
                // Shared code for handling children.
                // Returns (in this order):
                // - Whether there's a possible CRLF seam that needs fixing.
                // - Whether the tree may need invariant fixing.
                // - Updated TextInfo of the node.
                let handle_child = |children: &mut NodeChildren,
                                    child_i: usize,
                                    c_char_acc: usize|
                 -> (bool, bool, TextInfo) {
                    // Recurse into child
                    let tmp_info = children.info()[child_i];
                    let tmp_chars = children.info()[child_i].chars as usize;
                    let (new_info, seam, needs_fix) =
                        Arc::make_mut(&mut children.nodes_mut()[child_i]).remove_char_range(
                            start_idx - c_char_acc.min(start_idx),
                            (end_idx - c_char_acc).min(tmp_chars),
                            tmp_info,
                        );
                    // Handle result
                    if new_info.bytes == 0 {
                        children.remove(child_i);
                    } else {
                        children.info_mut()[child_i] = new_info;
                    }
                    (seam, needs_fix, new_info)
                };
                // Shared code for merging children
                let merge_child = |children: &mut NodeChildren, child_i: usize| {
                    if child_i < children.len()
                        && children.len() > 1
                        && children.nodes()[child_i].is_undersized()
                    {
                        if child_i == 0 {
                            children.merge_distribute(child_i, child_i + 1);
                        } else {
                            children.merge_distribute(child_i - 1, child_i);
                        }
                    }
                };
                // Get child info for the two char indices
                let ((l_child_i, l_char_acc), (r_child_i, r_char_acc)) =
                    children.search_char_idx_range(start_idx, end_idx);
                // Both indices point into the same child
                if l_child_i == r_child_i {
                    let info = children.info()[l_child_i];
                    let (seam, mut needs_fix, new_info) =
                        handle_child(children, l_child_i, l_char_acc);
                    if children.len() > 0 {
                        merge_child(children, l_child_i);
                        // If we couldn't get all children >= minimum size, then
                        // we'll need to fix that later.
                        if children.nodes()[l_child_i.min(children.len() - 1)].is_undersized() {
                            needs_fix = true;
                        }
                    }
                    return (node_info - info + new_info, seam, needs_fix);
                }
                // We're dealing with more than one child.
                else {
                    let mut needs_fix = false;
                    // Calculate the start..end range of nodes to be removed.
                    let r_child_exists: bool;
                    let start_i = l_child_i + 1;
                    let end_i = if r_char_acc + children.info()[r_child_i].chars as usize == end_idx
                    {
                        r_child_exists = false;
                        r_child_i + 1
                    } else {
                        r_child_exists = true;
                        r_child_i
                    };
                    // Remove the children
                    for _ in start_i..end_i {
                        children.remove(start_i);
                    }
                    // Handle right child
                    if r_child_exists {
                        let (_, fix, _) = handle_child(children, l_child_i + 1, r_char_acc);
                        needs_fix |= fix;
                    }
                    // Handle left child
                    let (seam, fix, _) = handle_child(children, l_child_i, l_char_acc);
                    needs_fix |= fix;
                    if children.len() > 0 {
                        // Handle merging
                        let merge_extent = 1 + if r_child_exists { 1 } else { 0 };
                        for i in (l_child_i..(l_child_i + merge_extent)).rev() {
                            merge_child(children, i);
                        }
                        // If we couldn't get all children >= minimum size, then
                        // we'll need to fix that later.
                        if children.nodes()[l_child_i.min(children.len() - 1)].is_undersized() {
                            needs_fix = true;
                        }
                    }
                    // Return
                    return (children.combined_info(), seam, needs_fix);
                }
            }
        }
    }
pub fn remove_char_range ( & mut self , start_idx : usize , end_idx : usize , node_info : TextInfo , ) -> ( TextInfo , bool , bool ) { if start_idx == end_idx { return ( node_info , false , false ) ; } match * self { // If it's a leaf Node :: Leaf ( ref mut leaf_text ) => { let byte_start = char_to_byte_idx ( leaf_text , start_idx ) ; let byte_end = byte_start + char_to_byte_idx ( & leaf_text [ byte_start .. ] , end_idx - start_idx ) ; // Remove text and calculate new info & seam info if byte_start > 0 || byte_end < leaf_text . len ( ) { let seam = ( byte_start == 0 && leaf_text . as_bytes ( ) [ byte_end ] == 0x0A ) || ( byte_end == leaf_text . len ( ) && leaf_text . as_bytes ( ) [ byte_start - 1 ] == 0x0D ) ; let seg_len = byte_end - byte_start ; // Length of removal segement if seg_len < ( leaf_text . len ( ) - seg_len ) { let mut info = node_info - TextInfo :: from_str ( & leaf_text [ byte_start .. byte_end ] ) ; // Check for CRLF pairs on the removal seams, and // adjust line break counts accordingly. if byte_end < leaf_text . len ( ) && leaf_text . as_bytes ( ) [ byte_end - 1 ] == 0x0D && leaf_text . as_bytes ( ) [ byte_end ] == 0x0A { info . line_breaks += 1 ; } if byte_start > 0 && leaf_text . as_bytes ( ) [ byte_start - 1 ] == 0x0D { if leaf_text . as_bytes ( ) [ byte_start ] == 0x0A { info . line_breaks += 1 ; } if byte_end < leaf_text . len ( ) && leaf_text . as_bytes ( ) [ byte_end ] == 0x0A { info . line_breaks -= 1 ; } } // Remove the text leaf_text . remove_range ( byte_start , byte_end ) ; ( info , seam , false ) } else { // Remove the text leaf_text . remove_range ( byte_start , byte_end ) ; ( TextInfo :: from_str ( & leaf_text ) , seam , false ) } } else { // Remove all of the text leaf_text . remove_range ( byte_start , byte_end ) ; ( TextInfo :: new ( ) , true , false ) } } // If it's internal, it's much more complicated Node :: Internal ( ref mut children ) => { // Shared code for handling children. // Returns (in this order): // - Whether there's a possible CRLF seam that needs fixing. // - Whether the tree may need invariant fixing. // - Updated TextInfo of the node. let handle_child = | children : & mut NodeChildren , child_i : usize , c_char_acc : usize | -> ( bool , bool , TextInfo ) { // Recurse into child let tmp_info = children . info ( ) [ child_i ] ; let tmp_chars = children . info ( ) [ child_i ] . chars as usize ; let ( new_info , seam , needs_fix ) = Arc :: make_mut ( & mut children . nodes_mut ( ) [ child_i ] ) . remove_char_range ( start_idx - c_char_acc . min ( start_idx ) , ( end_idx - c_char_acc ) . min ( tmp_chars ) , tmp_info , ) ; // Handle result if new_info . bytes == 0 { children . remove ( child_i ) ; } else { children . info_mut ( ) [ child_i ] = new_info ; } ( seam , needs_fix , new_info ) } ; // Shared code for merging children let merge_child = | children : & mut NodeChildren , child_i : usize | { if child_i < children . len ( ) && children . len ( ) > 1 && children . nodes ( ) [ child_i ] . is_undersized ( ) { if child_i == 0 { children . merge_distribute ( child_i , child_i + 1 ) ; } else { children . merge_distribute ( child_i - 1 , child_i ) ; } } } ; // Get child info for the two char indices let ( ( l_child_i , l_char_acc ) , ( r_child_i , r_char_acc ) ) = children . search_char_idx_range ( start_idx , end_idx ) ; // Both indices point into the same child if l_child_i == r_child_i { let info = children . info ( ) [ l_child_i ] ; let ( seam , mut needs_fix , new_info ) = handle_child ( children , l_child_i , l_char_acc ) ; if children . len ( ) > 0 { merge_child ( children , l_child_i ) ; // If we couldn't get all children >= minimum size, then // we'll need to fix that later. if children . nodes ( ) [ l_child_i . min ( children . len ( ) - 1 ) ] . is_undersized ( ) { needs_fix = true ; } } return ( node_info - info + new_info , seam , needs_fix ) ; } // We're dealing with more than one child. else { let mut needs_fix = false ; // Calculate the start..end range of nodes to be removed. let r_child_exists : bool ; let start_i = l_child_i + 1 ; let end_i = if r_char_acc + children . info ( ) [ r_child_i ] . chars as usize == end_idx { r_child_exists = false ; r_child_i + 1 } else { r_child_exists = true ; r_child_i } ; // Remove the children for _ in start_i .. end_i { children . remove ( start_i ) ; } // Handle right child if r_child_exists { let ( _ , fix , _ ) = handle_child ( children , l_child_i + 1 , r_char_acc ) ; needs_fix |= fix ; } // Handle left child let ( seam , fix , _ ) = handle_child ( children , l_child_i , l_char_acc ) ; needs_fix |= fix ; if children . len ( ) > 0 { // Handle merging let merge_extent = 1 + if r_child_exists { 1 } else { 0 } ; for i in ( l_child_i .. ( l_child_i + merge_extent ) ) . rev ( ) { merge_child ( children , i ) ; } // If we couldn't get all children >= minimum size, then // we'll need to fix that later. if children . nodes ( ) [ l_child_i . min ( children . len ( ) - 1 ) ] . is_undersized ( ) { needs_fix = true ; } } // Return return ( children . combined_info ( ) , seam , needs_fix ) ; } } } }
Removes chars in the range `start_idx..end_idx`.
Removes chars in the range ` start_idx .. end_idx ` .
&mut self
start_idx
usize
end_idx
usize
node_info
TextInfo