use std::fmt;
use koto_memory::Address;
use crate::{KString, Vm};
#[derive(Default)]
pub struct DisplayContext<'a> {
result: String,
vm: Option<&'a Vm>,
parent_containers: Vec<Address>,
}
impl<'a> DisplayContext<'a> {
pub fn with_vm(vm: &'a Vm) -> Self {
Self {
result: String::default(),
vm: Some(vm),
parent_containers: Vec::default(),
}
}
pub fn with_vm_and_capacity(vm: &'a Vm, capacity: usize) -> Self {
Self {
result: String::with_capacity(capacity),
vm: Some(vm),
parent_containers: Vec::default(),
}
}
pub fn append<'b>(&mut self, s: impl Into<StringBuilderAppend<'b>>) {
s.into().append(&mut self.result);
}
pub fn result(self) -> String {
self.result
}
pub fn vm(&self) -> &Option<&'a Vm> {
&self.vm
}
pub fn is_contained(&self) -> bool {
!self.parent_containers.is_empty()
}
pub fn is_in_parents(&self, id: Address) -> bool {
self.parent_containers
.iter()
.any(|parent_id| *parent_id == id)
}
pub fn push_container(&mut self, id: Address) {
self.parent_containers.push(id);
}
pub fn pop_container(&mut self) {
self.parent_containers.pop();
}
}
impl<'a> fmt::Write for DisplayContext<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.append(s);
Ok(())
}
}
pub enum StringBuilderAppend<'a> {
Char(char),
Str(&'a str),
String(String),
KString(KString),
KStringRef(&'a KString),
}
impl From<char> for StringBuilderAppend<'_> {
fn from(value: char) -> Self {
StringBuilderAppend::Char(value)
}
}
impl<'a> From<&'a str> for StringBuilderAppend<'a> {
fn from(value: &'a str) -> Self {
StringBuilderAppend::Str(value)
}
}
impl From<String> for StringBuilderAppend<'_> {
fn from(value: String) -> Self {
StringBuilderAppend::String(value)
}
}
impl From<KString> for StringBuilderAppend<'_> {
fn from(value: KString) -> Self {
StringBuilderAppend::KString(value)
}
}
impl<'a> From<&'a KString> for StringBuilderAppend<'a> {
fn from(value: &'a KString) -> Self {
StringBuilderAppend::KStringRef(value)
}
}
impl<'a> StringBuilderAppend<'a> {
fn append(self, string: &mut String) {
match self {
StringBuilderAppend::Char(c) => string.push(c),
StringBuilderAppend::Str(s) => string.push_str(s),
StringBuilderAppend::String(s) => string.push_str(&s),
StringBuilderAppend::KString(s) => string.push_str(&s),
StringBuilderAppend::KStringRef(s) => string.push_str(s),
}
}
}