1use swift::constructor::Constructor;
4use swift::field::Field;
5use swift::method::Method;
6use swift::modifier::Modifier;
7use swift::Swift;
8use {Cons, IntoTokens};
9use {Element, Tokens};
10
11#[derive(Debug, Clone)]
13pub struct Struct<'el> {
14    pub modifiers: Vec<Modifier>,
16    pub fields: Vec<Field<'el>>,
18    pub constructors: Vec<Constructor<'el>>,
20    pub methods: Vec<Method<'el>>,
22    pub implements: Vec<Swift<'el>>,
24    pub parameters: Tokens<'el, Swift<'el>>,
26    attributes: Tokens<'el, Swift<'el>>,
28    name: Cons<'el>,
30}
31
32impl<'el> Struct<'el> {
33    pub fn new<N>(name: N) -> Struct<'el>
35    where
36        N: Into<Cons<'el>>,
37    {
38        Struct {
39            modifiers: vec![Modifier::Public],
40            fields: vec![],
41            methods: vec![],
42            constructors: vec![],
43            parameters: Tokens::new(),
44            attributes: Tokens::new(),
45            name: name.into(),
46            implements: vec![],
47        }
48    }
49
50    pub fn attributes<A>(&mut self, attribute: A)
52    where
53        A: IntoTokens<'el, Swift<'el>>,
54    {
55        self.attributes.push(attribute.into_tokens());
56    }
57
58    pub fn name(&self) -> Cons<'el> {
60        self.name.clone()
61    }
62}
63
64into_tokens_impl_from!(Struct<'el>, Swift<'el>);
65
66impl<'el> IntoTokens<'el, Swift<'el>> for Struct<'el> {
67    fn into_tokens(self) -> Tokens<'el, Swift<'el>> {
68        let mut sig = Tokens::new();
69
70        sig.extend(self.modifiers.into_tokens());
71        sig.append("struct");
72
73        sig.append({
74            let mut t = Tokens::new();
75
76            t.append(self.name.clone());
77
78            if !self.parameters.is_empty() {
79                t.append("<");
80                t.append(self.parameters.join(", "));
81                t.append(">");
82            }
83
84            t
85        });
86
87        if !self.implements.is_empty() {
88            let implements: Tokens<_> = self
89                .implements
90                .into_iter()
91                .map::<Element<_>, _>(Into::into)
92                .collect();
93
94            sig.append(":");
95            sig.append(implements.join(", "));
96        }
97
98        let mut s = Tokens::new();
99
100        if !self.attributes.is_empty() {
101            s.push(self.attributes);
102        }
103
104        s.push(toks![sig.join_spacing(), " {"]);
105
106        s.nested({
107            let mut body = Tokens::new();
108
109            if !self.fields.is_empty() {
110                for field in self.fields {
111                    body.push(field);
112                }
113            }
114
115            if !self.constructors.is_empty() {
116                for constructor in self.constructors {
117                    body.push(constructor);
118                }
119            }
120
121            if !self.methods.is_empty() {
122                for method in self.methods {
123                    body.push(method);
124                }
125            }
126
127            body.join_line_spacing()
128        });
129
130        s.push("}");
131
132        s
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use swift::struct_::Struct;
139    use swift::Swift;
140    use Tokens;
141
142    #[test]
143    fn test_vec() {
144        let mut c = Struct::new("Foo");
145        c.parameters.append("T");
146        let t: Tokens<Swift> = c.into();
147
148        let s = t.to_string();
149        let out = s.as_ref().map(|s| s.as_str());
150        assert_eq!(Ok("public struct Foo<T> {\n}"), out);
151    }
152}