use core::fmt;
use alloc::string::String;
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::io;
#[cfg(feature = "serde-edits")]
use serde::{Deserialize, Serialize};
use crate::yaml::data::{Data, Id, StringId};
use crate::yaml::raw::{Null, Raw, NEWLINE};
use crate::yaml::{Value, ValueMut};
#[derive(Clone)]
#[cfg_attr(feature = "serde-edits", derive(Serialize, Deserialize))]
pub struct Document {
suffix: StringId,
pub(crate) root: Id,
pub(crate) data: Data,
}
impl Document {
#[must_use]
pub fn new() -> Self {
let mut data = Data::default();
let prefix = data.insert_str(b"");
let root = data.insert(Raw::Null(Null::Empty), prefix, None);
let suffix = data.insert_str([NEWLINE]);
Self { suffix, root, data }
}
pub(crate) fn from_parsed(suffix: StringId, root: Id, data: Data) -> Self {
Self { suffix, root, data }
}
#[must_use]
#[inline]
pub fn as_ref(&self) -> Value<'_> {
Value::new(&self.data, self.root)
}
pub fn as_mut(&mut self) -> ValueMut<'_> {
ValueMut::new(&mut self.data, self.root)
}
#[must_use]
#[inline]
pub fn value(&self, id: Id) -> Value<'_> {
Value::new(&self.data, id)
}
pub fn value_mut(&mut self, id: Id) -> ValueMut<'_> {
ValueMut::new(&mut self.data, id)
}
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub fn write_to<O>(&self, mut output: O) -> io::Result<()>
where
O: io::Write,
{
output.write_all(self.data.prefix(self.root))?;
self.data.raw(self.root).write_to(&self.data, &mut output)?;
output.write_all(self.data.str(self.suffix))?;
Ok(())
}
fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
use core::fmt::Display;
self.data.prefix(self.root).fmt(f)?;
self.data.raw(self.root).display(&self.data, f, None)?;
self.data.str(self.suffix).fmt(f)?;
Ok(())
}
}
impl fmt::Display for Document {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(feature = "std")]
if cfg!(nondestructive_write_to_eq) {
use bstr::BStr;
use std::fmt::Write;
#[repr(transparent)]
struct Inner<'a>(&'a Document);
impl fmt::Display for Inner<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.display(f)
}
}
let mut string = String::new();
write!(string, "{}", Inner(self))?;
let mut bytes = Vec::new();
self.write_to(&mut bytes)
.expect("Document::write_to should not panic");
debug_assert_eq!(
BStr::new(string.as_bytes()),
BStr::new(&bytes),
"nondestructive_write_to_eq: ensure write_to produces the same output"
);
return string.fmt(f);
}
self.display(f)
}
}
impl fmt::Debug for Document {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Document")
.field("suffix", &self.suffix)
.field("root", &self.root)
.finish_non_exhaustive()
}
}