Create io::Reader instance for TextBuffer
This commit is contained in:
parent
01b1ed1591
commit
d95ab09180
|
|
@ -1,2 +1,2 @@
|
||||||
mod text_buffer;
|
mod text_buffer;
|
||||||
pub use text_buffer::TextBuffer;
|
pub use text_buffer::{TextBuffer, TextBufferReader};
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ mod rope;
|
||||||
use rope::Rope;
|
use rope::Rope;
|
||||||
pub use rope::{CharIterator, CharWithPointIterator};
|
pub use rope::{CharIterator, CharWithPointIterator};
|
||||||
|
|
||||||
|
mod reader;
|
||||||
|
pub use reader::TextBufferReader;
|
||||||
|
|
||||||
pub struct TextBuffer {
|
pub struct TextBuffer {
|
||||||
contents: Rc<Rope>,
|
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
|
/// 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)
|
NodeIterator::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +269,7 @@ fn merge(leaf_nodes: &[Rc<Rope>]) -> Rc<Rope> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeIterator {
|
pub struct NodeIterator {
|
||||||
stack: Vec<Rc<Rope>>,
|
stack: Vec<Rc<Rope>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue