pub fn replace_cursor(
        &mut self,
        prefix_count: usize,
        insertable: Insertable,
    ) -> EditResult<Node::Class> {
        let (node_count, class) = match insertable {
            Insertable::CountedNode(count, c) => (
                count,
                Node::Class::from_char(c).ok_or(EditErr::CharNotANode(c))?,
            ),
        };
        // If `count` is 0, then the replacement is exactly equivalent to deleting the cursor.
        //
        // Ideally, replacement should just be implemented as deletion followed by insertion (which
        // would fix at least one existing bug with replacement in JSON objects), but that is not
        // possible in the current architecture because nodes like Json::Field cannot have their
        // children deleted.
        if node_count == 0 {
            self.delete_cursor(prefix_count)?;
            return Ok(EditSuccess::Replace(class));
        }

        // check if on the root
        // get current node's parent
        if prefix_count != 1 {
            if let (_, Some(parent)) = self.cursor_and_parent() {
                // Do boundary check
                let max_index = parent.children().len() - 1;
                // we can unwrap current_cursor_path can't be empty
                let current_child_index = self.current_cursor_path.last().unwrap();
                if current_child_index + prefix_count > max_index {
                    return Err(EditErr::ReplaceError {
                        current_child_index,
                        last_child_index: max_index,
                        node_count: prefix_count,
                    });
                }
            };
        }

        self.perform_edit(
            |this: &mut Self,
             _parent_and_index: Option<(&'arena Node, usize)>,
             cursor: &'arena Node| {
                // Early return if the `class` can't go in the cursor's location
                match _parent_and_index {
                    Some((parent, _cursor_index)) => {
                        let mut cloned_parent = parent.clone();
                        // We can unwrap here, because we know that the cursor is not at the
                        // root and therefore there is at least one segment of the Path.
                        let next_cursor_index = this.current_cursor_path.last_mut().unwrap();
                        // Loop over the prefix count, so that the correct number of nodes get
                        // replaced
                        for _ in 0..prefix_count {
                            // Each time a node gets replaced, replace it with the nodes specified
                            // by the Insertable
                            for j in 0..node_count {
                                let insert_index = *next_cursor_index + j;
                                // Check that the new node would be valid in the insert location,
                                // and return if so
                                if !cloned_parent.is_valid_child(insert_index, class) {
                                    return Err(EditErr::CannotBeChild {
                                        class,
                                        parent_name: parent.display_name(),
                                    });
                                }
                                let new_node = this.arena.alloc(Node::from_class(class));
                                // Because of the short-circuit deletion rule, we know that there
                                // must be at least one node to insert.  Therefore, we can use the
                                // first of these to replace the cursor and treat the rest as
                                // insertions.
                                if j == 0 {
                                    cloned_parent.replace_child(insert_index, new_node);
                                } else {
                                    cloned_parent.insert_child(
                                        new_node,
                                        this.arena,
                                        insert_index,
                                    )?;
                                }
                            }
                            // Move the cursor to **one past** the last node.  This is so that the
                            // next loop iteration starts replacing the next node, and this effect
                            // is corrected by subtracting one after the loop.
                            *next_cursor_index += node_count;
                        }
                        // This will not underflow unless node_count == 0, in which case the
                        // delete short-circuit would stop this code executing
                        *next_cursor_index -= 1;
                        Ok((
                            cloned_parent,
                            EditLocation::Parent,
                            EditSuccess::Replace(class),
                        ))
                    }
                    None => {
                        match (prefix_count * node_count, cursor.is_valid_root(class)) {
                            // This path is unreachable because its condition would trigger the
                            // short-circuiting call to delete
                            (0, _) => unreachable!(),
                            // If we're replacing the root with exactly 1 invalid node, then that's
                            // not OK
                            (1, false) => Err(EditErr::CannotBeRoot(class)),
                            // If we're replacing the root with exactly 1 valid node then it's OK
                            // and we do the replacement
                            (1, true) => Ok((
                                Node::from_class(class),
                                EditLocation::Cursor,
                                EditSuccess::Replace(class),
                            )),
                            // If we're replacing the root with more than 1 node, then this is
                            // equivalent to adding siblings to the root
                            _ => Err(EditErr::AddSiblingToRoot),
                        }
                    }
                }
            },
        )
    }
/// Replaces the current cursor with a node represented by `c`
Replaces the current cursor with a node represented by `c`
Replaces the current cursor with a node represented by ` c `
pub fn replace_cursor(
        &mut self,
        prefix_count: usize,
        insertable: Insertable,
    ) -> EditResult<Node::Class> {
        let (node_count, class) = match insertable {
            Insertable::CountedNode(count, c) => (
                count,
                Node::Class::from_char(c).ok_or(EditErr::CharNotANode(c))?,
            ),
        };
        // If `count` is 0, then the replacement is exactly equivalent to deleting the cursor.
        //
        // Ideally, replacement should just be implemented as deletion followed by insertion (which
        // would fix at least one existing bug with replacement in JSON objects), but that is not
        // possible in the current architecture because nodes like Json::Field cannot have their
        // children deleted.
        if node_count == 0 {
            self.delete_cursor(prefix_count)?;
            return Ok(EditSuccess::Replace(class));
        }
        // check if on the root
        // get current node's parent
        if prefix_count != 1 {
            if let (_, Some(parent)) = self.cursor_and_parent() {
                // Do boundary check
                let max_index = parent.children().len() - 1;
                // we can unwrap current_cursor_path can't be empty
                let current_child_index = self.current_cursor_path.last().unwrap();
                if current_child_index + prefix_count > max_index {
                    return Err(EditErr::ReplaceError {
                        current_child_index,
                        last_child_index: max_index,
                        node_count: prefix_count,
                    });
                }
            };
        }
        self.perform_edit(
            |this: &mut Self,
             _parent_and_index: Option<(&'arena Node, usize)>,
             cursor: &'arena Node| {
                // Early return if the `class` can't go in the cursor's location
                match _parent_and_index {
                    Some((parent, _cursor_index)) => {
                        let mut cloned_parent = parent.clone();
                        // We can unwrap here, because we know that the cursor is not at the
                        // root and therefore there is at least one segment of the Path.
                        let next_cursor_index = this.current_cursor_path.last_mut().unwrap();
                        // Loop over the prefix count, so that the correct number of nodes get
                        // replaced
                        for _ in 0..prefix_count {
                            // Each time a node gets replaced, replace it with the nodes specified
                            // by the Insertable
                            for j in 0..node_count {
                                let insert_index = *next_cursor_index + j;
                                // Check that the new node would be valid in the insert location,
                                // and return if so
                                if !cloned_parent.is_valid_child(insert_index, class) {
                                    return Err(EditErr::CannotBeChild {
                                        class,
                                        parent_name: parent.display_name(),
                                    });
                                }
                                let new_node = this.arena.alloc(Node::from_class(class));
                                // Because of the short-circuit deletion rule, we know that there
                                // must be at least one node to insert.  Therefore, we can use the
                                // first of these to replace the cursor and treat the rest as
                                // insertions.
                                if j == 0 {
                                    cloned_parent.replace_child(insert_index, new_node);
                                } else {
                                    cloned_parent.insert_child(
                                        new_node,
                                        this.arena,
                                        insert_index,
                                    )?;
                                }
                            }
                            // Move the cursor to **one past** the last node.  This is so that the
                            // next loop iteration starts replacing the next node, and this effect
                            // is corrected by subtracting one after the loop.
                            *next_cursor_index += node_count;
                        }
                        // This will not underflow unless node_count == 0, in which case the
                        // delete short-circuit would stop this code executing
                        *next_cursor_index -= 1;
                        Ok((
                            cloned_parent,
                            EditLocation::Parent,
                            EditSuccess::Replace(class),
                        ))
                    }
                    None => {
                        match (prefix_count * node_count, cursor.is_valid_root(class)) {
                            // This path is unreachable because its condition would trigger the
                            // short-circuiting call to delete
                            (0, _) => unreachable!(),
                            // If we're replacing the root with exactly 1 invalid node, then that's
                            // not OK
                            (1, false) => Err(EditErr::CannotBeRoot(class)),
                            // If we're replacing the root with exactly 1 valid node then it's OK
                            // and we do the replacement
                            (1, true) => Ok((
                                Node::from_class(class),
                                EditLocation::Cursor,
                                EditSuccess::Replace(class),
                            )),
                            // If we're replacing the root with more than 1 node, then this is
                            // equivalent to adding siblings to the root
                            _ => Err(EditErr::AddSiblingToRoot),
                        }
                    }
                }
            },
        )
    }
pub fn replace_cursor ( & mut self , prefix_count : usize , insertable : Insertable , ) -> EditResult < Node :: Class > { let ( node_count , class ) = match insertable { Insertable :: CountedNode ( count , c ) => ( count , Node :: Class :: from_char ( c ) . ok_or ( EditErr :: CharNotANode ( c ) ) ? , ) , } ; // If `count` is 0, then the replacement is exactly equivalent to deleting the cursor. // // Ideally, replacement should just be implemented as deletion followed by insertion (which // would fix at least one existing bug with replacement in JSON objects), but that is not // possible in the current architecture because nodes like Json::Field cannot have their // children deleted. if node_count == 0 { self . delete_cursor ( prefix_count ) ? ; return Ok ( EditSuccess :: Replace ( class ) ) ; } // check if on the root // get current node's parent if prefix_count != 1 { if let ( _ , Some ( parent ) ) = self . cursor_and_parent ( ) { // Do boundary check let max_index = parent . children ( ) . len ( ) - 1 ; // we can unwrap current_cursor_path can't be empty let current_child_index = self . current_cursor_path . last ( ) . unwrap ( ) ; if current_child_index + prefix_count > max_index { return Err ( EditErr :: ReplaceError { current_child_index , last_child_index : max_index , node_count : prefix_count , } ) ; } } ; } self . perform_edit ( | this : & mut Self , _parent_and_index : Option < ( & ' arena Node , usize ) > , cursor : & ' arena Node | { // Early return if the `class` can't go in the cursor's location match _parent_and_index { Some ( ( parent , _cursor_index ) ) => { let mut cloned_parent = parent . clone ( ) ; // We can unwrap here, because we know that the cursor is not at the // root and therefore there is at least one segment of the Path. let next_cursor_index = this . current_cursor_path . last_mut ( ) . unwrap ( ) ; // Loop over the prefix count, so that the correct number of nodes get // replaced for _ in 0 .. prefix_count { // Each time a node gets replaced, replace it with the nodes specified // by the Insertable for j in 0 .. node_count { let insert_index = * next_cursor_index + j ; // Check that the new node would be valid in the insert location, // and return if so if ! cloned_parent . is_valid_child ( insert_index , class ) { return Err ( EditErr :: CannotBeChild { class , parent_name : parent . display_name ( ) , } ) ; } let new_node = this . arena . alloc ( Node :: from_class ( class ) ) ; // Because of the short-circuit deletion rule, we know that there // must be at least one node to insert.  Therefore, we can use the // first of these to replace the cursor and treat the rest as // insertions. if j == 0 { cloned_parent . replace_child ( insert_index , new_node ) ; } else { cloned_parent . insert_child ( new_node , this . arena , insert_index , ) ? ; } } // Move the cursor to **one past** the last node.  This is so that the // next loop iteration starts replacing the next node, and this effect // is corrected by subtracting one after the loop. * next_cursor_index += node_count ; } // This will not underflow unless node_count == 0, in which case the // delete short-circuit would stop this code executing * next_cursor_index -= 1 ; Ok ( ( cloned_parent , EditLocation :: Parent , EditSuccess :: Replace ( class ) , ) ) } None => { match ( prefix_count * node_count , cursor . is_valid_root ( class ) ) { // This path is unreachable because its condition would trigger the // short-circuiting call to delete ( 0 , _ ) => unreachable ! ( ) , // If we're replacing the root with exactly 1 invalid node, then that's // not OK ( 1 , false ) => Err ( EditErr :: CannotBeRoot ( class ) ) , // If we're replacing the root with exactly 1 valid node then it's OK // and we do the replacement ( 1 , true ) => Ok ( ( Node :: from_class ( class ) , EditLocation :: Cursor , EditSuccess :: Replace ( class ) , ) ) , // If we're replacing the root with more than 1 node, then this is // equivalent to adding siblings to the root _ => Err ( EditErr :: AddSiblingToRoot ) , } } } } , ) }
Replaces the current cursor with a node represented by `c`
Replaces the current cursor with a node represented by ` c `
&mut self
prefix_count
usize
insertable
Insertable
&mut self
prefix_count
usize
insertable
Insertable