1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#![cfg_attr(not(feature = "default"), allow(dead_code))]

use crate::Trait;

#[inline]
pub fn reuse_a_trait(t: Trait) -> ! {
    panic!("The trait `{:?}` is repeatedly used.", t)
}

#[inline]
pub fn trait_not_used(t: Trait) -> ! {
    panic!("The `{:?}` trait is not used.", t)
}

#[inline]
pub fn trait_not_support_union(t: Trait) -> ! {
    panic!("The `{:?}` trait does not support to a union.", t)
}

#[inline]
pub fn attribute_incorrect_format(attribute_name: &str, correct_usage: &[&str]) -> ! {
    panic!(
        "You are using an incorrect format of the `{}` attribute.{}",
        attribute_name,
        concat_string_slice_array(correct_usage)
    )
}

#[inline]
pub fn parameter_incorrect_format(parameter_name: &str, correct_usage: &[&str]) -> ! {
    panic!(
        "You are using an incorrect format of the `{}` parameter.{}",
        parameter_name,
        concat_string_slice_array(correct_usage)
    )
}

#[inline]
pub fn derive_attribute_not_set_up_yet(attribute_name: &str) -> ! {
    panic!(
        "You are using `{}` in the `derive` attribute, but it has not been set up yet.",
        attribute_name
    )
}

#[inline]
pub fn reset_parameter(parameter_name: &str) -> ! {
    panic!("Try to reset the `{}` parameter.", parameter_name)
}

#[inline]
pub fn unknown_parameter(attribute_name: &str, parameter_name: &str) -> ! {
    panic!("Unknown parameter `{}` used in the `{}` attribute.", parameter_name, attribute_name)
}

#[inline]
pub fn set_value_expression() -> ! {
    panic!("The default value and the expression parameter can not be set at the same time.")
}

#[inline]
pub fn set_expression_bound() -> ! {
    panic!("You don't need to set the expression and the bound at the same time.")
}

#[inline]
pub fn no_default_field() -> ! {
    panic!("There is no field set as default.")
}

#[inline]
pub fn multiple_default_fields() -> ! {
    panic!("Multiple default fields are set.")
}

#[inline]
pub fn no_default_variant() -> ! {
    panic!("There is no variant set as default.")
}

#[inline]
pub fn multiple_default_variants() -> ! {
    panic!("Multiple default variants are set.")
}

#[inline]
pub fn no_deref_field() -> ! {
    panic!("There is no field which is assigned for `Deref`.")
}

#[inline]
pub fn no_deref_field_of_variant(variant_name: &str) -> ! {
    panic!(
        "There is no field for the `{variant_name}` variant which is assigned for `Deref`.",
        variant_name = variant_name
    )
}

#[inline]
pub fn multiple_deref_fields() -> ! {
    panic!("Multiple fields are set for `Deref`.")
}

#[inline]
pub fn multiple_deref_fields_of_variant(variant_name: &str) -> ! {
    panic!(
        "Multiple fields of the `{variant_name}` variant are set for deref.",
        variant_name = variant_name
    )
}

#[inline]
pub fn deref_cannot_support_unit_variant() -> ! {
    panic!("The `Deref` trait cannot be implemented for an enum which has unit variants.")
}

#[inline]
pub fn no_deref_mut_field() -> ! {
    panic!("There is no field which is assigned for `DerefMut`.")
}

#[inline]
pub fn no_deref_mut_field_of_variant(variant_name: &str) -> ! {
    panic!(
        "There is no field for the `{variant_name}` variant which is assigned for `DerefMut`.",
        variant_name = variant_name
    )
}

#[inline]
pub fn multiple_deref_mut_fields() -> ! {
    panic!("Multiple fields are set for `DerefMut`.")
}

#[inline]
pub fn multiple_deref_mut_fields_of_variant(variant_name: &str) -> ! {
    panic!(
        "Multiple fields of the `{variant_name}` variant are set for `DerefMut`.",
        variant_name = variant_name
    )
}

#[inline]
pub fn deref_mut_cannot_support_unit_variant() -> ! {
    panic!("The `DerefMut` trait cannot be implemented for an enum which has unit variants.")
}

#[inline]
pub fn disable_named_field_name() -> ! {
    panic!("You can't disable the name of a named field.")
}

#[inline]
pub fn empty_parameter(parameter_name: &str) -> ! {
    panic!("You can't set the `{}` parameter to empty.", parameter_name)
}

#[inline]
pub fn unit_struct_need_name() -> ! {
    panic!("A unit struct needs to have a name.")
}

#[inline]
pub fn unit_enum_need_name() -> ! {
    panic!("A unit enum needs to have a name.")
}

#[inline]
pub fn unit_variant_need_name() -> ! {
    panic!("A unit variant which doesn't use an enum name needs to have a name.")
}

#[inline]
pub fn ignore_ranked_field() -> ! {
    panic!("You can't ignore a ranked field.")
}

#[inline]
pub fn reuse_a_rank(rank: isize) -> ! {
    panic!("The rank `{}` is repeatedly used.", rank)
}

#[inline]
pub fn reuse_a_value(value: isize) -> ! {
    panic!("The value `{}` is repeatedly used.", value)
}

// TODO patterns

#[inline]
pub fn educe_format_incorrect() -> ! {
    attribute_incorrect_format("educe", &[stringify!(#[educe(Trait1, Trait2, ..., TraitN)])])
}

fn concat_string_slice_array(array: &[&str]) -> String {
    let len = array.len();

    if len == 0 {
        String::new()
    } else {
        let mut string = String::from(" It needs to be formed into ");

        let mut iter = array.iter();

        let first = iter.next().unwrap();

        string.push('`');
        string.push_str(&first.replace('\n', ""));
        string.push('`');

        if len > 2 {
            for s in iter.take(len - 2) {
                string.push_str(", `");
                string.push_str(&s.replace('\n', ""));
                string.push('`');
            }
        }

        if len > 1 {
            string.push_str(", or `");
            string.push_str(&array[len - 1].replace('\n', ""));
            string.push('`');
        }

        string.push('.');

        string
    }
}