vespe 0.1.2

Text as a Canvas for LLM Collaboration and Automation
Documentation
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::collections::BTreeMap;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum JsonPlusEntity {
    Flag,
    Boolean(bool),
    Integer(i64),
    Float(f64),
    SingleQuotedString(String),
    DoubleQuotedString(String),
    NudeString(String),
    Object(JsonPlusObject),
    Array(Vec<JsonPlusEntity>),
}

impl JsonPlusEntity {
    pub fn as_string_only(&self) -> Option<String> {
        match self {
            JsonPlusEntity::NudeString(x)
            | JsonPlusEntity::SingleQuotedString(x)
            | JsonPlusEntity::DoubleQuotedString(x) => Some(x.clone()),
            _ => None,
        }
    }
    pub fn as_bool(&self) -> Option<bool> {
        match self {
            JsonPlusEntity::Flag => Some(true),
            JsonPlusEntity::Boolean(x) => Some(*x),
            JsonPlusEntity::Integer(x) => Some(*x != 0),
            JsonPlusEntity::Float(x) => Some(*x != 0.0f64),
            _ => None,
        }
    }
    pub fn as_object(&self) -> Option<&JsonPlusObject> {
        match self {
            JsonPlusEntity::Object(x) => Some(x),
            _ => None,
        }
    }
    pub fn as_integer_only(&self) -> Option<i64> {
        match self {
            JsonPlusEntity::Integer(x) => Some(*x),
            _ => None,
        }
    }
    pub fn to_prompt(&self) -> String {
        match self {
            JsonPlusEntity::Flag => String::new(),
            JsonPlusEntity::Boolean(x) => {
                format!("{}", if *x { "true" } else { "false" })
            }
            JsonPlusEntity::Integer(x) => format!("{}", x),
            JsonPlusEntity::Float(x) => format!("{}", x),
            JsonPlusEntity::SingleQuotedString(x) => format!("{}", x),
            JsonPlusEntity::DoubleQuotedString(x) => format!("{}", x),
            JsonPlusEntity::NudeString(x) => format!("{}", x),
            JsonPlusEntity::Object(x) => {
                format!("{}", Self::_object_to_string_0(x, ""))
            }
            JsonPlusEntity::Array(x) => {
                format!("{}", Self::_array_to_string_0(x, ""))
            }
        }
    }
    fn _to_string_0(&self, prefix: &str, pre_indent: &str) -> String {
        match self {
            JsonPlusEntity::Flag => String::new(),
            JsonPlusEntity::Boolean(x) => {
                format!("{}{}", prefix, if *x { "true" } else { "false" })
            }
            JsonPlusEntity::Integer(x) => format!("{}{}", prefix, x),
            JsonPlusEntity::Float(x) => format!("{}{}", prefix, x),
            JsonPlusEntity::SingleQuotedString(x) => format!("{}'{}'", prefix, x),
            JsonPlusEntity::DoubleQuotedString(x) => format!("{}\"{}\"", prefix, x),
            JsonPlusEntity::NudeString(x) => format!("{}{}", prefix, x),
            JsonPlusEntity::Object(x) => {
                format!("{}{}", prefix, Self::_object_to_string_0(x, pre_indent))
            }
            JsonPlusEntity::Array(x) => {
                format!("{}{}", prefix, Self::_array_to_string_0(x, pre_indent))
            }
        }
    }
    fn _array_to_string_0(array: &Vec<JsonPlusEntity>, pre_indent: &str) -> String {
        let mut s = format!("[");
        let n = array.len();
        let (separator, pre_indent, indent) = match n {
            0 | 1 => (" ", "", "".into()),
            _ => ("\n", pre_indent, format!("\t{}", pre_indent)),
        };
        let mut first = true;
        for value in array {
            if !first {
                s.push_str(",");
            }
            first = false;
            s.push_str(&separator);
            s.push_str(&indent);
            s.push_str(&value._to_string_0("", &indent));
        }
        if !first {
            s.push_str(&separator);
            s.push_str(pre_indent);
        }
        s.push_str("]");
        s
    }
    fn _object_to_string_0(object: &JsonPlusObject, pre_indent: &str) -> String {
        let mut s = format!("{{");
        let n = object.properties.len();
        let (separator, pre_indent, indent) = match n {
            0 | 1 => (" ", "", "".into()),
            _ => ("\n", pre_indent, format!("\t{}", pre_indent)),
        };
        let mut first = true;
        for (key, value) in &object.properties {
            if !first {
                s.push_str(",");
            }
            first = false;
            s.push_str(&separator);
            s.push_str(&indent);
            s.push_str(&key);
            s.push_str(&value._to_string_0(": ", &indent));
        }
        if !first {
            s.push_str(&separator);
            s.push_str(pre_indent);
        }
        s.push_str("}");
        s
    }
}

impl ToString for JsonPlusEntity {
    fn to_string(&self) -> String {
        JsonPlusEntity::_to_string_0(&self, "", "")
    }
}

impl From<&JsonPlusEntity> for serde_json::Value {
    fn from(jpe: &JsonPlusEntity) -> Self {
        match jpe {
            JsonPlusEntity::Flag => true.into(),
            JsonPlusEntity::Boolean(x) => (*x).into(),
            JsonPlusEntity::Integer(x) => (*x).into(),
            JsonPlusEntity::Float(x) => (*x).into(),
            JsonPlusEntity::SingleQuotedString(x) => x.clone().into(),
            JsonPlusEntity::DoubleQuotedString(x) => x.clone().into(),
            JsonPlusEntity::NudeString(x) => x.clone().into(),
            JsonPlusEntity::Array(x) => {
                Value::Array(x.iter().map(|x| x.into()).collect::<Vec<Value>>())
            }
            JsonPlusEntity::Object(x) => x.into(),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JsonPlusObject {
    pub properties: BTreeMap<String, JsonPlusEntity>,
}

impl From<&JsonPlusObject> for serde_json::Value {
    fn from(jpo: &JsonPlusObject) -> Self {
        Value::Object(
            jpo.properties
                .iter()
                .map(|(x, y)| (x.clone(), y.into()))
                .collect::<Map<String, Value>>(),
        )
    }
}

impl JsonPlusObject {
    pub fn new() -> Self {
        JsonPlusObject {
            properties: BTreeMap::new(),
        }
    }
    pub fn from_map(properties: BTreeMap<String, JsonPlusEntity>) -> Self {
        JsonPlusObject { properties }
    }
    pub fn insert(&mut self, key: String, value: JsonPlusEntity) {
        self.properties.insert(key, value);
    }
    pub fn get(&self, key: &str) -> Option<&JsonPlusEntity> {
        self.properties.get(key)
    }
    pub fn get_as_object(&self, key: &str) -> Option<&JsonPlusObject> {
        match self.get(key) {
            None => None,
            Some(x) => x.as_object(),
        }
    }
    pub fn get_as_bool(&self, key: &str) -> Option<bool> {
        match self.get(key) {
            None => None,
            Some(x) => x.as_bool(),
        }
    }
    pub fn get_as_string_only(&self, key: &str) -> Option<String> {
        match self.get(key) {
            None => None,
            Some(x) => x.as_string_only(),
        }
    }
    pub fn get_as_integer_only(&self, key: &str) -> Option<i64> {
        match self.get(key) {
            None => None,
            Some(x) => x.as_integer_only(),
        }
    }
}

impl ToString for JsonPlusObject {
    fn to_string(&self) -> String {
        JsonPlusEntity::_object_to_string_0(&self, "")
    }
}