186 lines
5.5 KiB
Plaintext
186 lines
5.5 KiB
Plaintext
Heading 2 Reader API
|
|
class mt-12
|
|
Markdown
|
|
The [Document API](#document-api) requires `Reader` implementations to iterate through lines
|
|
in a document. A reader is any type that implements the `Reader` trait, which provides
|
|
an async method to read the next line from a source.
|
|
|
|
Terrace provides built-in readers for common use cases, but you can implement the trait
|
|
for your own custom sources.
|
|
|
|
Heading 3 Reader Trait
|
|
class mb-4 mt-12
|
|
Markdown
|
|
The Reader trait defines the interface for reading lines from a document source.
|
|
Implement this trait to create custom readers for different input sources.
|
|
|
|
CodeBlock rust
|
|
// Trait Definition
|
|
#[async_trait::async_trait]
|
|
pub trait Reader {
|
|
/// Read the next line from the source.
|
|
/// Returns None if there are no more lines.
|
|
async fn read_line(&mut self) -> io::Result<Option<String>>;
|
|
}
|
|
|
|
Heading 3 StringReader
|
|
class mb-4 mt-12
|
|
Markdown
|
|
| Parameter | Type | Description
|
|
| -------------- | --------------------- | -----------------------------------------------------------------------
|
|
| source | impl Into<StringReaderSource> | The source content as a string or vector of strings.
|
|
| **@returns** | [StringReader](#string-reader) | A reader that iterates over the lines in the source.
|
|
|
|
A reader that reads from a string or vector of strings. This is the most common reader
|
|
for parsing Terrace documents from memory.
|
|
|
|
CodeBlock rust
|
|
// Struct Definition
|
|
pub struct StringReader {
|
|
// Implementation details...
|
|
}
|
|
|
|
// Constructor
|
|
pub fn new(source: impl Into<StringReaderSource>) -> Self
|
|
|
|
// Import Path
|
|
use terrace::readers::StringReader;
|
|
|
|
// Usage
|
|
// From a string
|
|
let reader = StringReader::new("line1\nline2\nline3");
|
|
|
|
// From a vector of strings
|
|
let reader = StringReader::new(vec!["line1", "line2", "line3"]);
|
|
|
|
// From a string slice
|
|
let reader = StringReader::new("line1\nline2\nline3");
|
|
|
|
Heading 3 AsyncReader
|
|
class mb-4 mt-12
|
|
Markdown
|
|
| Parameter | Type | Description
|
|
| -------------- | --------------------- | -----------------------------------------------------------------------
|
|
| reader | R | Any async reader that implements AsyncRead.
|
|
| **@returns** | [AsyncReader](#async-reader)<R> | A reader that reads lines from an async source.
|
|
|
|
A reader that reads from any async source that implements the `AsyncRead` trait.
|
|
This is useful for reading from files, network streams, or other async sources.
|
|
|
|
CodeBlock rust
|
|
// Struct Definition
|
|
pub struct AsyncReader<R> {
|
|
// Implementation details...
|
|
}
|
|
|
|
// Constructor
|
|
pub fn new(reader: R) -> Self
|
|
|
|
// Import Path
|
|
use terrace::readers::AsyncReader;
|
|
use tokio::fs::File;
|
|
|
|
// Usage
|
|
let file = File::open("document.tce").await?;
|
|
let reader = AsyncReader::new(file);
|
|
|
|
// Can also be used with other async sources
|
|
use tokio::io::BufReader;
|
|
let buffered = BufReader::new(file);
|
|
let reader = AsyncReader::new(buffered);
|
|
|
|
Heading 3 Custom Reader Implementation
|
|
class mb-4 mt-12
|
|
Markdown
|
|
You can implement the Reader trait for your own custom sources. This allows you
|
|
to read from databases, APIs, or any other source of line-based data.
|
|
|
|
CodeBlock rust
|
|
// Custom Reader Example
|
|
use async_trait::async_trait;
|
|
use std::io;
|
|
use terrace::readers::Reader;
|
|
|
|
struct DatabaseReader {
|
|
connection: DatabaseConnection,
|
|
query: String,
|
|
current_row: usize,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Reader for DatabaseReader {
|
|
async fn read_line(&mut self) -> io::Result<Option<String>> {
|
|
// Fetch next row from database
|
|
match self.connection.fetch_row(&self.query, self.current_row).await {
|
|
Ok(Some(row)) => {
|
|
self.current_row += 1;
|
|
Ok(Some(format!("{} {}", row.key, row.value)))
|
|
}
|
|
Ok(None) => Ok(None),
|
|
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Usage
|
|
let db_reader = DatabaseReader {
|
|
connection: connect_to_db().await?,
|
|
query: "SELECT key, value FROM config".to_string(),
|
|
current_row: 0,
|
|
};
|
|
|
|
let mut doc = TerraceDocument::with_reader(db_reader);
|
|
while let Some(node) = doc.next().await {
|
|
println!("{}: {}", node.head(), node.tail());
|
|
}
|
|
|
|
Heading 3 Reader Trait Implementation Details
|
|
class mb-4 mt-12
|
|
Markdown
|
|
When implementing the Reader trait, follow these guidelines:
|
|
|
|
- Return `Ok(Some(line))` for each line of content
|
|
- Return `Ok(None)` when there are no more lines
|
|
- Return `Err(error)` if an I/O error occurs
|
|
- Lines should not include trailing newlines
|
|
- The reader should be mutable to track state between calls
|
|
|
|
CodeBlock rust
|
|
// Complete Reader Implementation Example
|
|
use async_trait::async_trait;
|
|
use std::io;
|
|
use terrace::readers::Reader;
|
|
|
|
struct VecReader {
|
|
lines: Vec<String>,
|
|
index: usize,
|
|
}
|
|
|
|
impl VecReader {
|
|
fn new(lines: Vec<String>) -> Self {
|
|
Self { lines, index: 0 }
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Reader for VecReader {
|
|
async fn read_line(&mut self) -> io::Result<Option<String>> {
|
|
if self.index >= self.lines.len() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let line = self.lines[self.index].clone();
|
|
self.index += 1;
|
|
Ok(Some(line))
|
|
}
|
|
}
|
|
|
|
// Usage
|
|
let lines = vec![
|
|
"config".to_string(),
|
|
" database".to_string(),
|
|
" host localhost".to_string(),
|
|
];
|
|
let reader = VecReader::new(lines);
|
|
let mut doc = TerraceDocument::with_reader(reader);
|