1use std::fmt::{self, Write};
2
3use crate::bound::Bound;
4use crate::field::Field;
5use crate::formatter::{fmt_bounds, fmt_generics, Formatter};
6use crate::function::Function;
7
8use crate::r#type::Type;
9
10#[derive(Debug, Clone)]
12pub struct Impl {
13 target: Type,
15
16 generics: Vec<String>,
18
19 impl_trait: Option<Type>,
21
22 assoc_csts: Vec<Field>,
24
25 assoc_tys: Vec<Field>,
27
28 bounds: Vec<Bound>,
30
31 fns: Vec<Function>,
32
33 macros: Vec<String>,
34}
35
36impl Impl {
37 pub fn new<T>(target: T) -> Self
39 where
40 T: Into<Type>,
41 {
42 Impl {
43 target: target.into(),
44 generics: vec![],
45 impl_trait: None,
46 assoc_csts: vec![],
47 assoc_tys: vec![],
48 bounds: vec![],
49 fns: vec![],
50 macros: vec![],
51 }
52 }
53
54 pub fn generic(&mut self, name: &str) -> &mut Self {
58 self.generics.push(name.to_string());
59 self
60 }
61
62 pub fn target_generic<T>(&mut self, ty: T) -> &mut Self
64 where
65 T: Into<Type>,
66 {
67 self.target.generic(ty);
68 self
69 }
70
71 pub fn impl_trait<T>(&mut self, ty: T) -> &mut Self
73 where
74 T: Into<Type>,
75 {
76 self.impl_trait = Some(ty.into());
77 self
78 }
79
80 pub fn r#macro(&mut self, r#macro: &str) -> &mut Self {
82 self.macros.push(r#macro.to_string());
83 self
84 }
85
86 pub fn associate_const<T>(
88 &mut self,
89 name: impl Into<String>,
90 ty: T,
91 value: impl Into<String>,
92 visibility: impl Into<String>,
93 ) -> &mut Self
94 where
95 T: Into<Type>,
96 {
97 self.assoc_csts.push(Field {
98 name: name.into(),
99 ty: ty.into(),
100 documentation: String::new(),
101 annotation: Vec::new(),
102 value: value.into(),
103 visibility: Some(visibility.into()),
104 });
105
106 self
107 }
108
109 pub fn associate_type<T>(&mut self, name: &str, ty: T) -> &mut Self
111 where
112 T: Into<Type>,
113 {
114 self.assoc_tys.push(Field {
115 name: name.to_string(),
116 ty: ty.into(),
117 documentation: String::new(),
118 annotation: Vec::new(),
119 value: String::new(),
120 visibility: None,
121 });
122
123 self
124 }
125
126 pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
128 where
129 T: Into<Type>,
130 {
131 self.bounds.push(Bound {
132 name: name.to_string(),
133 bound: vec![ty.into()],
134 });
135 self
136 }
137
138 pub fn new_fn(&mut self, name: &str) -> &mut Function {
140 self.push_fn(Function::new(name));
141 self.fns.last_mut().unwrap()
142 }
143
144 pub fn push_fn(&mut self, item: Function) -> &mut Self {
146 self.fns.push(item);
147 self
148 }
149
150 pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
152 for m in self.macros.iter() {
153 write!(fmt, "{}\n", m)?;
154 }
155 write!(fmt, "impl")?;
156 fmt_generics(&self.generics[..], fmt)?;
157
158 if let Some(ref t) = self.impl_trait {
159 write!(fmt, " ")?;
160 t.fmt(fmt)?;
161 write!(fmt, " for")?;
162 }
163
164 write!(fmt, " ")?;
165 self.target.fmt(fmt)?;
166
167 fmt_bounds(&self.bounds, fmt)?;
168
169 fmt.block(|fmt| {
170 if !self.assoc_csts.is_empty() {
172 for cst in &self.assoc_csts {
173 if let Some(vis) = &cst.visibility {
174 write!(fmt, "{} ", vis)?;
175 }
176 write!(fmt, "const {}: ", cst.name)?;
177 cst.ty.fmt(fmt)?;
178 write!(fmt, " = {};\n", cst.value)?;
179 }
180 }
181
182 if !self.assoc_tys.is_empty() {
184 for ty in &self.assoc_tys {
185 write!(fmt, "type {} = ", ty.name)?;
186 ty.ty.fmt(fmt)?;
187 write!(fmt, ";\n")?;
188 }
189 }
190
191 for (i, func) in self.fns.iter().enumerate() {
192 if i != 0 || !self.assoc_tys.is_empty() {
193 write!(fmt, "\n")?;
194 }
195
196 func.fmt(false, fmt)?;
197 }
198
199 Ok(())
200 })
201 }
202}