use std::fmt;
use koto_memory::Address;
use crate::{KString, KotoVm};
#[derive(Default)]
pub struct DisplayContext<'a> {
result: String,
vm: Option<&'a KotoVm>,
parent_containers: Vec<Address>,
debug: bool,
}
impl<'a> DisplayContext<'a> {
pub fn with_vm(vm: &'a KotoVm) -> Self {
Self {
result: String::default(),
vm: Some(vm),
parent_containers: Vec::default(),
debug: false,
}
}
pub fn with_vm_and_capacity(vm: &'a KotoVm, capacity: usize) -> Self {
Self {
result: String::with_capacity(capacity),
vm: Some(vm),
parent_containers: Vec::default(),
debug: false,
}
}
pub fn enable_debug(mut self) -> Self {
self.debug = true;
self
}
pub fn result(self) -> String {
self.result
}
pub fn append<'b>(&mut self, s: impl Into<StringBuilderAppend<'b>>) {
s.into().append(&mut self.result);
}
pub fn vm(&self) -> &Option<&'a KotoVm> {
&self.vm
}
pub fn debug_enabled(&self) -> bool {
self.debug
}
pub fn is_contained(&self) -> bool {
!self.parent_containers.is_empty()
}
pub fn is_in_parents(&self, id: Address) -> bool {
self.parent_containers.contains(&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 fmt::Write for DisplayContext<'_> {
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 StringBuilderAppend<'_> {
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),
}
}
}