use pie_core::{ElemPool, PieList};
const ORIGINAL_TEXT: &str = "the world is a fine place and worth fighting for.";
const ADD_BUFFER: &str = "beautiful ";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Buffer {
Original,
Add,
}
#[derive(Debug, Clone, Copy)]
struct Piece {
buffer: Buffer,
start: usize,
len: usize,
}
impl Piece {
fn get_text<'a>(&self, original: &'a str, add: &'a str) -> &'a str {
let text = match self.buffer {
Buffer::Original => original,
Buffer::Add => add,
};
&text[self.start..self.start + self.len]
}
}
fn print_document(
list: &PieList<Piece>,
pool: &ElemPool<Piece>,
original: &str,
add: &str,
) {
print!(" Reconstructed Text: \"" );
for piece in list.iter(pool) {
print!("{}", piece.get_text(original, add));
}
println!("\"");
}
fn print_list_state(list: &PieList<Piece>, pool: &ElemPool<Piece>) {
println!(" Internal PieList state:");
print!(" [");
let mut first = true;
for piece in list.iter(pool) {
if !first {
print!( ", ");
}
print!(
"Piece({:?}, {}, {})",
piece.buffer,
piece.start,
piece.len
);
first = false;
}
println!("]");
}
fn main() {
println!("---\n--- PieList Text Editor Simulation ---\n");
let mut pool = ElemPool::<Piece>::new();
let mut document = PieList::new(&mut pool);
println!("1. Initial State");
let initial_piece = Piece {
buffer: Buffer::Original,
start: 0,
len: ORIGINAL_TEXT.len(),
};
document.push_back(initial_piece, &mut pool).unwrap();
print_document(&document, &pool, ORIGINAL_TEXT, ADD_BUFFER);
print_list_state(&document, &pool);
println!(" A single piece points to the entire original document.\n");
println!("2. Insertion: Adding 'beautiful ' after 'the '");
println!(" ACTION: Manually split the first piece and insert a new one.");
let insertion_offset = 4; let text_to_insert = ADD_BUFFER;
let mut cursor = document.cursor_mut(&mut pool);
let original_piece = *cursor.peek(&pool).unwrap();
let before_piece = Piece {
len: insertion_offset,
..original_piece
};
let after_piece = Piece {
start: original_piece.start + insertion_offset,
len: original_piece.len - insertion_offset,
..original_piece
};
let add_piece = Piece {
buffer: Buffer::Add,
start: 0,
len: text_to_insert.len(),
};
*cursor.peek_mut(&mut pool).unwrap() = before_piece;
cursor.insert_after(after_piece, &mut pool).unwrap();
cursor.insert_after(add_piece, &mut pool).unwrap();
print_document(&document, &pool, ORIGINAL_TEXT, ADD_BUFFER);
print_list_state(&document, &pool);
println!(" The list is now three pieces. No original text was copied or moved.\n");
println!("3. Deletion: Removing ' and worth fighting for'");
println!(" ACTION: Find the piece and shorten it.");
let mut cursor = document
.cursor_mut_at(document.len() - 1, &mut pool)
.unwrap();
let piece_to_shorten = cursor.peek(&pool).unwrap();
let deletion_len = " and worth fighting for".len();
let new_len = piece_to_shorten.len - deletion_len;
cursor.peek_mut(&mut pool).unwrap().len = new_len;
println!("\n ACTION: Now, remove the middle piece ('beautiful ').");
cursor.move_prev(&mut pool);
let removed_piece = cursor.remove_current(&mut pool).unwrap();
print_document(&document, &pool, ORIGINAL_TEXT, ADD_BUFFER);
print_list_state(&document, &pool);
println!(" The middle piece was removed (O(1)). The list is back to two pieces.\n");
println!("4. Undo: Use a second list and `splice_before` to restore the deleted piece.");
let mut undo_buffer = PieList::new(&mut pool);
undo_buffer.push_back(removed_piece, &mut pool).unwrap();
println!(" The 'undo_buffer' now holds the piece we removed.");
print!(" Undo Buffer State: ");
print!("[Piece({:?}, {}, {})]",
undo_buffer.front(&pool).unwrap().buffer,
undo_buffer.front(&pool).unwrap().start,
undo_buffer.front(&pool).unwrap().len);
println!();
println!("\n ACTION: Splice the undo_buffer back into the document.");
let mut cursor = document.cursor_mut(&mut pool);
cursor.move_next(&mut pool);
cursor.splice_before(&mut undo_buffer, &mut pool).unwrap();
assert!(undo_buffer.is_empty());
print_document(&document, &pool, ORIGINAL_TEXT, ADD_BUFFER);
print_list_state(&document, &pool);
println!(" The 'beautiful ' piece is back! The splice was a single O(1) operation.");
document.set_leak_check(false);
println!("\n--- Simulation complete ---");
}