use crate::buffer::{Buffer, VecBuffer};
use crate::format_element::{Document, FormatElement};
use crate::printer::{Printed, Printer, PrinterOptions};
pub type FormatResult<T> = Result<T, FormatError>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FormatError {
message: String,
}
impl FormatError {
#[must_use]
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
}
}
}
impl std::fmt::Display for FormatError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for FormatError {}
pub trait FormatContext {
type Options: FormatOptions;
fn options(&self) -> &Self::Options;
fn source_length_hint(&self) -> usize {
0
}
}
pub trait FormatOptions {
fn as_print_options(&self) -> PrinterOptions;
}
pub trait Format<Context> {
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()>;
}
impl<Context, T> Format<Context> for &T
where
T: Format<Context>,
{
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
(*self).fmt(formatter)
}
}
impl<Context, T> Format<Context> for Option<T>
where
T: Format<Context>,
{
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
if let Some(value) = self {
value.fmt(formatter)?;
}
Ok(())
}
}
impl<Context> Format<Context> for Document {
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
formatter.write_document(self.clone());
Ok(())
}
}
impl<Context> Format<Context> for FormatElement {
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
formatter.write_element(self.clone());
Ok(())
}
}
pub struct Formatter<Context> {
context: Context,
buffer: VecBuffer,
}
impl<Context> Formatter<Context>
where
Context: FormatContext,
{
#[must_use]
pub fn new(context: Context) -> Self {
let capacity = estimate_document_capacity(context.source_length_hint());
Self {
context,
buffer: VecBuffer::with_capacity(capacity),
}
}
}
impl<Context> Formatter<Context> {
#[must_use]
pub fn context(&self) -> &Context {
&self.context
}
pub fn context_mut(&mut self) -> &mut Context {
&mut self.context
}
pub fn write_element(&mut self, element: FormatElement) {
self.buffer.write_element(element);
}
pub fn write_document(&mut self, document: Document) {
self.buffer.write_elements(document.into_vec());
}
#[must_use]
pub fn finish(self) -> Formatted<Context> {
Formatted {
context: self.context,
document: Document::from_elements(self.buffer.into_vec()),
}
}
}
impl<Context> Buffer for Formatter<Context> {
fn write_element(&mut self, element: FormatElement) {
Formatter::write_element(self, element);
}
fn elements(&self) -> &[FormatElement] {
self.buffer.elements()
}
}
#[derive(Debug, Clone)]
pub struct Formatted<Context> {
context: Context,
document: Document,
}
impl<Context> Formatted<Context>
where
Context: FormatContext,
{
pub fn print(&self) -> FormatResult<Printed> {
let printer = Printer::new(self.context.options().as_print_options());
printer
.print_with_capacity(&self.document, self.context.source_length_hint())
.map_err(|err| FormatError::new(err.to_string()))
}
#[must_use]
pub fn context(&self) -> &Context {
&self.context
}
#[must_use]
pub fn document(&self) -> &Document {
&self.document
}
}
fn estimate_document_capacity(source_length_hint: usize) -> usize {
source_length_hint / 2
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SimpleFormatOptions {
pub printer_options: PrinterOptions,
}
impl FormatOptions for SimpleFormatOptions {
fn as_print_options(&self) -> PrinterOptions {
self.printer_options
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SimpleFormatContext {
pub options: SimpleFormatOptions,
}
impl SimpleFormatContext {
#[must_use]
pub fn new(options: SimpleFormatOptions) -> Self {
Self { options }
}
}
impl FormatContext for SimpleFormatContext {
type Options = SimpleFormatOptions;
fn options(&self) -> &Self::Options {
&self.options
}
}