1use std::fmt::{self, Write};
2
3use crate::field::Field;
4use crate::formatter::Formatter;
5
6use crate::r#type::Type;
7
8#[derive(Debug, Clone)]
10pub enum Fields {
11 Empty,
12 Tuple(Vec<Type>),
13 Named(Vec<Field>),
14}
15
16impl Fields {
17 pub fn push_named(&mut self, field: Field) -> &mut Self {
18 match *self {
19 Fields::Empty => {
20 *self = Fields::Named(vec![field]);
21 }
22 Fields::Named(ref mut fields) => {
23 fields.push(field);
24 }
25 _ => panic!("field list is named"),
26 }
27
28 self
29 }
30
31 pub fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
32 where
33 T: Into<Type>,
34 {
35 self.push_named(Field {
36 name: name.to_string(),
37 ty: ty.into(),
38 documentation: String::new(),
39 annotation: Vec::new(),
40 value: String::new(),
41 visibility: None,
42 })
43 }
44
45 pub fn new_named<T>(&mut self, name: impl Into<String>, ty: T) -> &mut Field
46 where
47 T: Into<Type>,
48 {
49 self.named(&name.into(), ty);
50 if let Fields::Named(ref mut fields) = *self {
51 fields.last_mut().unwrap()
52 } else {
53 unreachable!()
54 }
55 }
56
57 pub fn tuple<T>(&mut self, ty: T) -> &mut Self
58 where
59 T: Into<Type>,
60 {
61 match *self {
62 Fields::Empty => {
63 *self = Fields::Tuple(vec![ty.into()]);
64 }
65 Fields::Tuple(ref mut fields) => {
66 fields.push(ty.into());
67 }
68 _ => panic!("field list is tuple"),
69 }
70
71 self
72 }
73
74 pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
75 match *self {
76 Fields::Named(ref fields) => {
77 assert!(!fields.is_empty());
78
79 fmt.block(|fmt| {
80 for f in fields {
81 if !f.documentation.is_empty() {
82 for doc in f.documentation.lines() {
83 write!(fmt, "/// {}\n", doc)?;
84 }
85 }
86 if !f.annotation.is_empty() {
87 for ann in &f.annotation {
88 write!(fmt, "{}\n", ann)?;
89 }
90 }
91 if let Some(ref visibility) = f.visibility {
92 write!(fmt, "{} ", visibility)?;
93 }
94 write!(fmt, "{}: ", f.name)?;
95 f.ty.fmt(fmt)?;
96 write!(fmt, ",\n")?;
97 }
98
99 Ok(())
100 })?;
101 }
102 Fields::Tuple(ref tys) => {
103 assert!(!tys.is_empty());
104
105 write!(fmt, "(")?;
106
107 for (i, ty) in tys.iter().enumerate() {
108 if i != 0 {
109 write!(fmt, ", ")?;
110 }
111 ty.fmt(fmt)?;
112 }
113
114 write!(fmt, ")")?;
115 }
116 Fields::Empty => {}
117 }
118
119 Ok(())
120 }
121}