#![allow(clippy::missing_errors_doc)]
#[cfg(test)]
mod tests;
use crate::{Result, error::Error};
use facet::{Field, Shape, Variant};
use serde::{
Deserialize, Serialize, de, ser,
ser::{SerializeMap, SerializeStruct},
};
use std::{
cell::{Ref, RefCell, RefMut},
collections::BTreeMap,
fmt,
rc::Rc,
};
#[derive(Serialize, Deserialize, Debug, Eq, Clone, PartialEq, Hash, PartialOrd, Ord)]
#[serde(rename_all = "UPPERCASE")]
pub enum Namespace {
Root,
Named(String),
}
impl fmt::Display for Namespace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Namespace::Root => write!(f, "ROOT"),
Namespace::Named(name) => write!(f, "{name}"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Eq, Clone, PartialEq, Hash, PartialOrd, Ord)]
pub struct QualifiedTypeName {
pub namespace: Namespace,
pub name: String,
}
impl fmt::Display for QualifiedTypeName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}::{}", self.namespace, self.name)
}
}
impl From<&str> for QualifiedTypeName {
fn from(value: &str) -> Self {
if let Some((namespace, name)) = value.split_once(['.', '_']) {
Self::namespaced(namespace.to_string(), name.to_string())
} else {
Self::root(value.to_string())
}
}
}
impl QualifiedTypeName {
#[must_use]
pub fn root(name: String) -> Self {
Self {
namespace: Namespace::Root,
name,
}
}
#[must_use]
pub fn namespaced(namespace: String, name: String) -> Self {
Self {
namespace: Namespace::Named(namespace),
name,
}
}
#[must_use]
pub fn format(&self, namespace_formatter: fn(&str) -> String, separator: &str) -> String {
match &self.namespace {
Namespace::Root => self.name.clone(),
Namespace::Named(ns) => {
let namespace = namespace_formatter(ns);
let name = self.name.clone();
format!("{namespace}{separator}{name}")
}
}
}
}
#[derive(Serialize, Deserialize, Default, Debug, Eq, Clone, PartialEq)]
#[serde(transparent)]
pub struct Doc(Vec<String>);
impl Doc {
#[must_use]
pub fn new() -> Self {
Self(Vec::new())
}
pub fn push(&mut self, comment: String) {
self.0.push(comment);
}
#[must_use]
pub fn comments(&self) -> &[String] {
&self.0
}
}
impl From<&[&str]> for Doc {
fn from(comments: &[&str]) -> Self {
let doc = comments.iter().map(|c| c.trim().to_string()).collect();
Self(doc)
}
}
impl From<&Shape> for Doc {
fn from(shape: &Shape) -> Self {
shape.doc.into()
}
}
impl From<&Field> for Doc {
fn from(field: &Field) -> Self {
field.doc.into()
}
}
impl From<&Variant> for Doc {
fn from(variant: &Variant) -> Self {
variant.doc.into()
}
}
#[derive(Serialize, Deserialize, Debug, Eq, Clone, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub enum Format {
Variable(#[serde(with = "not_implemented")] Variable<Format>),
TypeName(QualifiedTypeName),
Unit,
Bool,
I8,
I16,
I32,
I64,
I128,
U8,
U16,
U32,
U64,
U128,
F32,
F64,
Char,
Str,
Bytes,
Option(Box<Format>),
Seq(Box<Format>),
Set(Box<Format>),
#[serde(rename_all = "UPPERCASE")]
Map {
key: Box<Format>,
value: Box<Format>,
},
Tuple(Vec<Format>),
#[serde(rename_all = "UPPERCASE")]
TupleArray {
content: Box<Format>,
size: usize,
},
}
#[derive(Serialize, Deserialize, Debug, Eq, Clone, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub enum ContainerFormat {
UnitStruct(Doc),
NewTypeStruct(Box<Format>, Doc),
TupleStruct(Vec<Format>, Doc),
Struct(Vec<Named<Format>>, Doc),
Enum(BTreeMap<u32, Named<VariantFormat>>, Doc),
}
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Named<T> {
pub name: String,
pub doc: Doc,
pub value: T,
}
impl<T> Named<T>
where
T: Clone,
{
#[must_use]
pub fn new(value: &T, name: String) -> Self {
Self {
name,
doc: Doc::default(),
value: value.clone(),
}
}
#[must_use]
pub fn without_docs(&self) -> Self {
Self {
doc: Doc::default(),
..self.clone()
}
}
}
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Variable<T>(Rc<RefCell<Option<T>>>);
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub enum VariantFormat {
Variable(#[serde(with = "not_implemented")] Variable<VariantFormat>),
Unit,
NewType(Box<Format>),
Tuple(Vec<Format>),
Struct(Vec<Named<Format>>),
}
pub trait FormatHolder {
fn visit<'a>(&'a self, f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()>;
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()>;
fn normalize(&mut self) -> Result<()> {
self.visit_mut(&mut |format: &mut Format| {
let normalized = match format {
Format::Tuple(formats) => {
let size = formats.len();
if size <= 1 {
return Ok(());
}
let format0 = &formats[0];
for format in formats.iter().skip(1) {
if format != format0 {
return Ok(());
}
}
Format::TupleArray {
content: Box::new(std::mem::take(&mut formats[0])),
size,
}
}
_ => {
return Ok(());
}
};
*format = normalized;
Ok(())
})
}
fn reduce(&mut self) {
self.visit_mut(&mut |_| Ok(())).unwrap_or(());
}
fn is_unknown(&self) -> bool;
}
impl FormatHolder for VariantFormat {
fn visit<'a>(&'a self, f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()> {
match self {
Self::Variable(variable) => variable.visit(f)?,
Self::Unit => (),
Self::NewType(format) => format.visit(f)?,
Self::Tuple(formats) => {
for format in formats {
format.visit(f)?;
}
}
Self::Struct(named_formats) => {
for format in named_formats {
format.visit(f)?;
}
}
}
Ok(())
}
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()> {
match self {
Self::Variable(variable) => {
variable.visit_mut(f)?;
*self = std::mem::take(variable)
.into_inner()
.expect("variable is known");
}
Self::Unit => (),
Self::NewType(format) => {
format.visit_mut(f)?;
}
Self::Tuple(formats) => {
for format in formats {
format.visit_mut(f)?;
}
}
Self::Struct(named_formats) => {
for format in named_formats {
format.visit_mut(f)?;
}
}
}
Ok(())
}
fn is_unknown(&self) -> bool {
if let Self::Variable(v) = self {
return v.is_unknown();
}
false
}
}
impl<T> FormatHolder for Named<T>
where
T: FormatHolder + fmt::Debug,
{
fn visit<'a>(&'a self, f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()> {
self.value.visit(f)
}
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()> {
self.value.visit_mut(f)
}
fn is_unknown(&self) -> bool {
false
}
}
impl<T> Variable<T> {
pub(crate) fn new(content: Option<T>) -> Self {
Self(Rc::new(RefCell::new(content)))
}
#[must_use]
pub fn borrow(&self) -> Ref<'_, Option<T>> {
self.0.as_ref().borrow()
}
#[must_use]
pub fn borrow_mut(&self) -> RefMut<'_, Option<T>> {
self.0.as_ref().borrow_mut()
}
}
impl<T> Variable<T>
where
T: Clone,
{
fn into_inner(self) -> Option<T> {
match Rc::try_unwrap(self.0) {
Ok(cell) => cell.into_inner(),
Err(rc) => rc.borrow().clone(),
}
}
}
mod not_implemented {
pub fn serialize<T, S>(_: &T, _serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
use serde::ser::Error;
Err(S::Error::custom("Cannot serialize variables"))
}
pub fn deserialize<'de, T, D>(_deserializer: D) -> Result<T, D::Error>
where
D: serde::de::Deserializer<'de>,
{
use serde::de::Error;
Err(D::Error::custom("Cannot deserialize variables"))
}
}
impl<T> FormatHolder for Variable<T>
where
T: FormatHolder + fmt::Debug + Clone,
{
fn visit<'a>(&'a self, _f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()> {
Err(Error::UnknownFormat)
}
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()> {
match &mut *self.borrow_mut() {
None => Err(Error::UnknownFormat),
Some(value) => value.visit_mut(f),
}
}
fn is_unknown(&self) -> bool {
match self.borrow().as_ref() {
None => true,
Some(format) => format.is_unknown(),
}
}
}
impl FormatHolder for ContainerFormat {
fn visit<'a>(&'a self, f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()> {
match self {
Self::UnitStruct(_doc) => (),
Self::NewTypeStruct(format, _doc) => format.visit(f)?,
Self::TupleStruct(formats, _doc) => {
for format in formats {
format.visit(f)?;
}
}
Self::Struct(named_formats, _doc) => {
for format in named_formats {
format.visit(f)?;
}
}
Self::Enum(variants, _doc) => {
for variant in variants {
variant.1.visit(f)?;
}
}
}
Ok(())
}
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()> {
match self {
Self::UnitStruct(_doc) => (),
Self::NewTypeStruct(format, _doc) => format.visit_mut(f)?,
Self::TupleStruct(formats, _doc) => {
for format in formats {
format.visit_mut(f)?;
}
}
Self::Struct(named_formats, _doc) => {
for format in named_formats {
format.visit_mut(f)?;
}
}
Self::Enum(variants, _doc) => {
for variant in variants {
variant.1.visit_mut(f)?;
}
}
}
Ok(())
}
fn is_unknown(&self) -> bool {
false
}
}
impl FormatHolder for Format {
fn visit<'a>(&'a self, f: &mut dyn FnMut(&'a Format) -> Result<()>) -> Result<()> {
match self {
Self::Variable(variable) => variable.visit(f)?,
Self::TypeName(_)
| Self::Unit
| Self::Bool
| Self::I8
| Self::I16
| Self::I32
| Self::I64
| Self::I128
| Self::U8
| Self::U16
| Self::U32
| Self::U64
| Self::U128
| Self::F32
| Self::F64
| Self::Char
| Self::Str
| Self::Bytes => (),
Self::Option(format)
| Self::Seq(format)
| Self::Set(format)
| Self::TupleArray {
content: format, ..
} => {
format.visit(f)?;
}
Self::Map { key, value } => {
key.visit(f)?;
value.visit(f)?;
}
Self::Tuple(formats) => {
for format in formats {
format.visit(f)?;
}
}
}
f(self)
}
fn visit_mut(&mut self, f: &mut dyn FnMut(&mut Format) -> Result<()>) -> Result<()> {
match self {
Self::Variable(variable) => {
variable.visit_mut(f)?;
*self = std::mem::take(variable)
.into_inner()
.expect("variable is known");
}
Self::TypeName(_)
| Self::Unit
| Self::Bool
| Self::I8
| Self::I16
| Self::I32
| Self::I64
| Self::I128
| Self::U8
| Self::U16
| Self::U32
| Self::U64
| Self::U128
| Self::F32
| Self::F64
| Self::Char
| Self::Str
| Self::Bytes => (),
Self::Option(format)
| Self::Seq(format)
| Self::Set(format)
| Self::TupleArray {
content: format, ..
} => {
format.visit_mut(f)?;
}
Self::Map { key, value } => {
key.visit_mut(f)?;
value.visit_mut(f)?;
}
Self::Tuple(formats) => {
for format in formats {
format.visit_mut(f)?;
}
}
}
f(self)
}
fn is_unknown(&self) -> bool {
if let Self::Variable(v) = self {
return v.is_unknown();
}
false
}
}
impl Format {
#[must_use]
pub fn unknown() -> Self {
Self::Variable(Variable::new(None))
}
}
impl VariantFormat {
#[must_use]
pub fn unknown() -> Self {
Self::Variable(Variable::new(None))
}
}
impl Default for Format {
fn default() -> Self {
Self::unknown()
}
}
impl Default for VariantFormat {
fn default() -> Self {
Self::unknown()
}
}
impl<T> Serialize for Named<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
if serializer.is_human_readable() {
let mut map = serializer.serialize_map(Some(1))?;
map.serialize_entry(&self.name, &(&self.value, &self.doc))?;
map.end()
} else {
let mut inner = serializer.serialize_struct("Named", 3)?;
inner.serialize_field("name", &self.name)?;
inner.serialize_field("value", &self.value)?;
inner.serialize_field("doc", &self.doc)?;
inner.end()
}
}
}
struct NamedVisitor<T> {
marker: std::marker::PhantomData<T>,
}
impl<T> NamedVisitor<T> {
fn new() -> Self {
Self {
marker: std::marker::PhantomData,
}
}
}
impl<'de, T> de::Visitor<'de> for NamedVisitor<T>
where
T: Deserialize<'de>,
{
type Value = Named<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a single entry map")
}
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: de::MapAccess<'de>,
{
let named_value = match access.next_entry::<String, T>()? {
Some((name, value)) => Named {
name,
doc: Doc::new(),
value,
},
_ => {
return Err(de::Error::custom("Missing entry"));
}
};
if access.next_entry::<String, T>()?.is_some() {
return Err(de::Error::custom("Too many entries"));
}
Ok(named_value)
}
}
#[derive(Deserialize)]
#[serde(rename = "Named")]
struct NamedInternal<T> {
name: String,
doc: Doc,
value: T,
}
impl<'de, T> Deserialize<'de> for Named<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Named<T>, D::Error>
where
D: de::Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_map(NamedVisitor::new())
} else {
let NamedInternal { name, doc, value } = NamedInternal::deserialize(deserializer)?;
Ok(Self { name, doc, value })
}
}
}