#[derive(Clone, Copy)]
pub struct DocumentedConstants {
names: &'static [&'static str],
types: &'static [&'static str],
values: &'static [&'static str],
docs: &'static [&'static [&'static str]],
}
impl DocumentedConstants {
pub fn constant_names(&self) -> &[&'static str] {
self.names
}
pub fn constant_types(&self) -> &[&'static str] {
self.types
}
pub fn constant_values(&self) -> &[&'static str] {
self.values
}
pub fn constant_docs_raw(&self) -> &[&[&'static str]] {
self.docs
}
pub fn constant_docs(&self) -> Vec<Vec<&'static str>> {
self.constant_docs_raw()
.iter().map(|x| {
x.into_iter()
.filter_map(|x| super::filter_docs(*x))
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
}
pub fn commented_constants(&self) -> String {
use std::fmt::Write;
let mut output = String::new();
assert_eq!(self.names.len(), self.types.len(), "Constant names and types length are not equal");
assert_eq!(self.names.len(), self.values.len(), "Constant names and values length are not equal");
assert_eq!(self.names.len(), self.docs.len(), "Constant names and docs length are not equal");
for (i, field) in self.names.iter().enumerate() {
if i != 0 {
write!(output, "\n").unwrap();
}
for comment in self.docs.get(i).unwrap().iter() {
if let Some(comment) = super::filter_docs(comment) {
write!(output, "///{}\n", comment).unwrap();
}
}
write!(output, "{}: {}\n", field, self.types.get(i).unwrap()).unwrap();
}
output
}
}
#[macro_export]
macro_rules! code_docs_constants {
(
$t_vis:vis $t_name:ident;
$(
$(#[$meta:meta])*
$vis:vis const $name:ident : $t:ty = $expr:expr ;
)*
) => {
$t_vis const $t_name: $crate::DocumentedConstants = $crate::DocumentedConstants {
names: &[
$(
stringify!($name),
)*
],
types: &[
$(
stringify!($t),
)*
],
values: &[
$(
stringify!($expr),
)*
],
docs: &[
$(
&[
$(stringify!($meta),)*
],
)*
],
};
$(
$(#[$meta])*
$vis const $name : $t = $expr ;
)*
}
}
#[cfg(test)]
#[allow(unused)]
mod tests {
code_docs_constants! {
pub DOCS;
const ENV_FEATURE1: &str = "something";
#[allow(unused)]
const ENV_FEATURE2: usize = 666;
}
#[test]
fn test_constants() {
assert_eq!(DOCS.constant_names(), &["ENV_FEATURE1", "ENV_FEATURE2"]);
assert_eq!(DOCS.constant_types(), &["&str", "usize"]);
assert_eq!(DOCS.constant_values(), &["\"something\"", "666"]);
assert_eq!(DOCS.constant_docs_raw(), vec![
vec![],
vec![
"doc = r\" Does the thing with feature2\"",
"doc = r\"\"",
"doc = r\" Yes very important\"",
"allow(unused)"
],
]);
assert_eq!(DOCS.constant_docs(), vec![
vec![],
vec![
" Does the thing with feature2",
"",
" Yes very important",
]]);
}
}