use crate::{WolframFunction, WolframValue};
use std::fmt::{Display, Formatter, Write};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ReadableWriter {
pub pretty: bool,
pub indent_string: &'static str,
}
impl Default for ReadableWriter {
fn default() -> Self {
Self { pretty: true, indent_string: " " }
}
}
struct ReadableBuffer {
buffer: String,
indent_level: usize,
config: ReadableWriter,
}
impl ReadableBuffer {
pub fn new(config: ReadableWriter) -> ReadableBuffer {
Self { buffer: String::new(), indent_level: 0, config }
}
pub fn write_value(&mut self, value: &WolframValue) -> std::fmt::Result {
match value {
WolframValue::Skip => Ok(()),
WolframValue::Function(v) => self.write_function(v),
WolframValue::Boolean(v) => match v {
true => write!(self.buffer, "True"),
false => write!(self.buffer, "False"),
},
WolframValue::String(s) => write!(self.buffer, "{:?}", s),
WolframValue::Bytes(b) => {
let v: Vec<String> = b.iter().map(|s| format!("{}", s)).collect();
write!(self.buffer, "ByteArray[{{{}}}]", v.join(","))
}
WolframValue::Symbol(s) => write!(self.buffer, "{}", s),
WolframValue::Integer8(i) => write!(self.buffer, "{}", i),
WolframValue::Integer16(i) => write!(self.buffer, "{}", i),
WolframValue::Integer32(i) => write!(self.buffer, "{}", i),
WolframValue::Integer64(i) => write!(self.buffer, "{}", i),
WolframValue::BigInteger(i) => write!(self.buffer, "{}", i),
WolframValue::Decimal64(d) => write!(self.buffer, "{}`", d.0),
WolframValue::BigDecimal(d) => write!(self.buffer, "{}", d),
WolframValue::PackedArray(_) => unimplemented!(),
WolframValue::NumericArray(_) => unimplemented!(),
WolframValue::Association(dict) => {
let v: Vec<String> = dict.iter().map(|(k, (r, v))| format!("{}{}{}", k, r, v)).collect();
write!(self.buffer, "<|{}|>", v.join(","))
}
}
}
pub fn write_function(&mut self, function: &WolframFunction) -> std::fmt::Result {
let head = function.get_head();
let args = function.get_rest();
self.indent();
if head.to_string() == "List" {
self.write_items(args, '{', '}')?;
}
else {
self.buffer.write_str(&head.to_string())?;
self.write_items(args, '[', ']')?;
}
self.dedent();
Ok(())
}
pub fn write_items(&mut self, items: &[WolframValue], lhs: char, rhs: char) -> std::fmt::Result {
self.buffer.write_char(lhs)?;
for (index, item) in items.iter().enumerate() {
if index != 0 {
self.buffer.write_char(',')?;
}
self.write_value(item)?;
self.write_new_line()?;
}
self.buffer.write_char(rhs)?;
Ok(())
}
pub fn write_new_line(&mut self) -> std::fmt::Result {
if self.config.pretty {
self.buffer.write_char('\n')?;
for _ in 0..self.indent_level {
self.buffer.write_str(self.config.indent_string)?;
}
}
Ok(())
}
pub fn indent(&mut self) {
self.indent_level += 1;
}
pub fn dedent(&mut self) {
self.indent_level -= 1;
}
}
impl Display for WolframFunction {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut buffer = ReadableBuffer::new(ReadableWriter { pretty: f.alternate(), indent_string: " " });
buffer.write_function(self)?;
write!(f, "{}", buffer.buffer)
}
}
impl Display for WolframValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut buffer = ReadableBuffer::new(ReadableWriter { pretty: f.alternate(), indent_string: " " });
buffer.write_value(self)?;
write!(f, "{}", buffer.buffer)
}
}