use core::any::TypeId;
use std::collections::HashMap;
use tracing::Level;
use crate::Origin;
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct FieldDescriptor {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub deprecated: Option<&'static str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub doc: Option<&'static str>,
#[cfg_attr(
feature = "serde",
serde(
skip_serializing_if = "serde::pairs_empty",
serialize_with = "serde::pairs"
)
)]
pub meta: &'static [(&'static str, &'static str)],
pub name: &'static str,
pub r#type: &'static str,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct MessageDescriptor {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub deprecated: Option<&'static str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub doc: Option<&'static str>,
pub fields: &'static [FieldDescriptor],
#[cfg_attr(feature = "serde", serde(serialize_with = "serde::level"))]
pub level: Level,
#[cfg_attr(
feature = "serde",
serde(
skip_serializing_if = "serde::pairs_empty",
serialize_with = "serde::pairs"
)
)]
pub meta: &'static [(&'static str, &'static str)],
#[cfg_attr(feature = "serde", serde(skip))]
pub msg: &'static str,
#[cfg_attr(feature = "serde", serde(serialize_with = "serde::origin"))]
pub origin: Origin,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "serde::tags_empty"))]
pub tags: &'static [&'static str],
#[cfg_attr(feature = "serde", serde(skip))]
pub type_id: TypeId,
}
#[cfg(feature = "serde")]
mod serde {
use ::serde::{Serializer, ser::SerializeMap};
use tracing::Level;
use crate::Origin;
pub(super) fn level<S: Serializer>(level: &Level, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&level.to_string())
}
pub(super) fn origin<S: Serializer>(origin: &Origin, s: S) -> Result<S::Ok, S::Error> {
s.collect_str(origin)
}
pub(super) fn pairs<S: Serializer>(
pairs: &&'static [(&'static str, &'static str)],
s: S,
) -> Result<S::Ok, S::Error> {
let mut map = s.serialize_map(Some(pairs.len()))?;
for (k, v) in pairs.iter() {
map.serialize_entry(k, v)?;
}
map.end()
}
pub(super) fn pairs_empty(pairs: &&'static [(&'static str, &'static str)]) -> bool {
pairs.is_empty()
}
pub(super) fn tags_empty(tags: &&'static [&'static str]) -> bool {
tags.is_empty()
}
}
pub fn all() -> impl Iterator<Item = &'static MessageDescriptor> {
inventory::iter::<MessageDescriptor>.into_iter()
}
pub fn duplicates() -> Vec<&'static str> {
let mut counts = HashMap::new();
for descriptor in all() {
*counts.entry(descriptor.msg).or_insert(0_usize) += 1;
}
let mut keys: Vec<&'static str> = counts
.into_iter()
.filter_map(|(msg, count)| (count > 1).then_some(msg))
.collect();
keys.sort_unstable();
keys
}
inventory::collect!(MessageDescriptor);