use super::*;
pub(super) fn comment(
ctxt: &mut Ctxt<'_, '_, '_>,
tag: Tag,
variants: &[&Variant],
) {
ctxt.out.append_comment(|comment| {
if comment.is_empty() {
swrite!(comment, "Possible variants:");
} else {
swrite!(comment, "; possible variants:");
}
});
for variant in variants {
comment_variant(ctxt, tag, variant);
}
}
fn comment_variant(ctxt: &mut Ctxt<'_, '_, '_>, tag: Tag, variant: &Variant) {
let rendered_variant = render_variant(ctxt, tag, variant);
let rendered_variant = rendered_variant
.lines()
.enumerate()
.map(|(line_idx, line)| {
if line_idx > 0 {
format!(" {}", line)
} else {
line.to_owned()
}
})
.collect::<Vec<_>>()
.join("\n");
let comment = if let Some(comment) = variant.comment {
Some(comment)
} else if variant.title != variant.id {
Some(variant.title)
} else {
None
};
let str = match comment {
Some(comment) => {
if rendered_variant.lines().count() == 1
&& comment.lines().count() == 1
{
format!("- {} = {}", rendered_variant, comment)
} else {
let mut str = String::new();
for (comment_line_idx, comment_line) in
comment.lines().enumerate()
{
if comment_line_idx == 0 {
swrite!(str, "- {}", comment_line);
} else {
swrite!(str, "\n {}", comment_line);
}
}
swrite!(str, "{}", rendered_variant);
str
}
}
None => format!("- {}", rendered_variant),
};
ctxt.out.writeln_comment(str);
}
fn render_variant(
ctxt: &Ctxt<'_, '_, '_>,
tag: Tag,
variant: &Variant,
) -> String {
match tag {
Tag::Adjacent { tag, content } => match &variant.fields {
Fields::Unit => {
format!("\n\t{} = \"{}\"\n", tag, variant.id,)
}
fields => {
let key_or_section = if fields.is_table() {
format!("[{}]\n\t", ctxt.name_for_child(content))
} else {
format!("{} = ", content)
};
format!(
"\n\t{} = \"{}\"\n\t{}{}\n",
tag,
variant.id,
key_or_section,
render_variant_fields(ctxt, fields, false, true),
)
}
},
Tag::Internal { tag } => match &variant.fields {
Fields::Named { fields } => {
if fields.is_empty() {
format!("\n\t{} = \"{}\"\n", tag, variant.id,)
} else {
format!(
"\n\t{} = \"{}\"\n\t{}\n",
tag,
variant.id,
render_variant_fields(
ctxt,
&variant.fields,
true,
true,
),
)
}
}
Fields::Unnamed { .. } => {
panic!("Internally tagged unnamed variants are unsupported in TOML")
}
Fields::Unit => format!("\n\t{} = \"{}\"\n", tag, variant.id,),
},
Tag::External => match &variant.fields {
Fields::Unit => {
format!("\"{}\"\n", variant.id)
}
fields => {
let key_or_section = if fields.is_table() {
format!("[{}]\n\t", ctxt.name_for_child(variant.id))
} else {
format!("{} = ", variant.id)
};
format!(
"\n\t{}{}\n",
key_or_section,
render_variant_fields(ctxt, fields, false, true),
)
}
},
Tag::None => render_variant_fields(ctxt, &variant.fields, false, false),
}
}
fn render_variant_fields(
ctxt: &Ctxt<'_, '_, '_>,
fields: &Fields,
flat: bool,
indent: bool,
) -> String {
let fmt = Formatting {
enums_style: EnumsStyle::Separated,
layout: Layout::OneColumn,
..ctxt.fmt.clone()
};
let mut out = Output::new(&fmt);
let mut ctxt = Ctxt {
ty: &<()>::ty(),
val: Default::default(),
vis: ctxt.vis,
fmt: &fmt,
out: &mut out,
is_key: Default::default(),
name: Default::default(),
parent: Default::default(),
example: Default::default(),
flat,
depth: Default::default(),
};
ctxt.print_fields(fields, None, false);
let out = out.render();
if indent {
out.lines()
.enumerate()
.map(|(line_idx, line)| {
if line_idx > 0 {
format!(" {}", line)
} else {
line.to_owned()
}
})
.collect::<Vec<_>>()
.join("\n")
} else {
out
}
}