Create io::Reader instance for TextBuffer
This commit is contained in:
parent
01b1ed1591
commit
d95ab09180
|
|
@ -1,2 +1,2 @@
|
|||
mod text_buffer;
|
||||
pub use text_buffer::TextBuffer;
|
||||
pub use text_buffer::{TextBuffer, TextBufferReader};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ mod rope;
|
|||
use rope::Rope;
|
||||
pub use rope::{CharIterator, CharWithPointIterator};
|
||||
|
||||
mod reader;
|
||||
pub use reader::TextBufferReader;
|
||||
|
||||
pub struct TextBuffer {
|
||||
contents: Rc<Rope>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use super::{
|
||||
TextBuffer,
|
||||
rope::{NodeIterator, Rope},
|
||||
};
|
||||
|
||||
pub struct TextBufferReader {
|
||||
node_iterator: NodeIterator,
|
||||
current_node: Option<Rc<Rope>>,
|
||||
cursor: usize,
|
||||
}
|
||||
|
||||
impl TextBufferReader {
|
||||
pub fn new(text_buffer: &TextBuffer) -> Self {
|
||||
let mut node_iterator = Rc::clone(&text_buffer.contents).iter_nodes();
|
||||
let current_node = node_iterator.next();
|
||||
Self {
|
||||
node_iterator,
|
||||
current_node,
|
||||
cursor: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::io::Read for TextBufferReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let mut bytes_written = 0;
|
||||
while let Some(rope) = self.current_node.clone() {
|
||||
if let Rope::Leaf { text } = rope.as_ref() {
|
||||
let bytes = text.as_bytes();
|
||||
let length = bytes
|
||||
.len()
|
||||
.min(buf.len() - bytes_written)
|
||||
.min(bytes.len() - self.cursor);
|
||||
buf[bytes_written..bytes_written + length]
|
||||
.copy_from_slice(&bytes[self.cursor..self.cursor + length]);
|
||||
bytes_written += length;
|
||||
self.cursor += length;
|
||||
if self.cursor == bytes.len() {
|
||||
self.current_node = self.node_iterator.next();
|
||||
self.cursor = 0;
|
||||
}
|
||||
} else {
|
||||
// Should always be leaf node
|
||||
panic!();
|
||||
}
|
||||
if bytes_written == buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(bytes_written)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::text_buffer::Point;
|
||||
use std::io::Read;
|
||||
|
||||
#[test]
|
||||
fn test_read_string() {
|
||||
let text_fragments = [
|
||||
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem ",
|
||||
"accusantium doloremque laudantium, totam rem aperiam, eaque ",
|
||||
"ipsa quae ab illo inventore veritatis et quasi architecto beatae ",
|
||||
"vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia ",
|
||||
"voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur ",
|
||||
"magni dolores eos qui ratione voluptatem sequi nesciunt. Neque ",
|
||||
"porro quisquam est, qui dolorem ipsum quia dolor sit amet, ",
|
||||
"consectetur, adipisci velit, sed quia non numquam eius modi tempora ",
|
||||
"incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut ",
|
||||
"enim ad minima veniam, quis nostrum exercitationem ullam ",
|
||||
"corporis suscipit laboriosam, nisi ut aliquid ex ea commodi ",
|
||||
"consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate ",
|
||||
"velit esse quam nihil molestiae consequatur, vel illum qui dolorem ",
|
||||
"eum fugiat quo voluptas nulla pariatur?",
|
||||
];
|
||||
let mut text_buffer = TextBuffer::new();
|
||||
for fragment in text_fragments {
|
||||
text_buffer.insert_text(fragment, Point::End);
|
||||
}
|
||||
let mut target = TextBufferReader::new(&text_buffer);
|
||||
let mut bytes_buffer = Vec::new();
|
||||
target.read_to_end(&mut bytes_buffer).unwrap();
|
||||
let target_string = String::from_utf8(bytes_buffer).unwrap();
|
||||
let expected_string: String = text_fragments.iter().flat_map(|s| s.chars()).collect();
|
||||
assert_eq!(target_string, expected_string);
|
||||
}
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ impl Rope {
|
|||
}
|
||||
|
||||
/// Returns an iterater over the leaf nodes
|
||||
fn iter_nodes(self: Rc<Self>) -> NodeIterator {
|
||||
pub fn iter_nodes(self: Rc<Self>) -> NodeIterator {
|
||||
NodeIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
|
@ -269,7 +269,7 @@ fn merge(leaf_nodes: &[Rc<Rope>]) -> Rc<Rope> {
|
|||
}
|
||||
}
|
||||
|
||||
struct NodeIterator {
|
||||
pub struct NodeIterator {
|
||||
stack: Vec<Rc<Rope>>,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue