enum_tools/generator/
features.rs

1use crate::feature::as_str_fn::{AsStrMode, FeatureAsStrFn};
2use crate::feature::debug_trait::FeatureDebugTrait;
3use crate::feature::display_trait::FeatureDisplayTrait;
4use crate::feature::from_str_fn::{FeatureFromStrFn, FromStrFnMode};
5use crate::feature::from_str_trait::{FeatureFromStrTrait, FromStrMode};
6use crate::feature::into_fn::FeatureIntoFn;
7use crate::feature::into_str_trait::FeatureIntoStrTrait;
8use crate::feature::into_trait::FeatureIntoTrait;
9use crate::feature::iter::{FeatureIter, IterMode};
10use crate::feature::max_const::FeatureMaxConst;
11use crate::feature::min_const::FeatureMinConst;
12use crate::feature::names::FeatureNames;
13use crate::feature::next_back_fn::FeatureNextBackFn;
14use crate::feature::next_fn::FeatureNextFn;
15use crate::feature::range_fn::FeatureRangeFn;
16use crate::feature::table_enum::FeatureTableEnum;
17use crate::feature::table_name::FeatureTableName;
18use crate::feature::table_range::FeatureTableRange;
19use crate::feature::try_from_fn::FeatureTryFromFn;
20use crate::feature::try_from_trait::FeatureTryFromTrait;
21use crate::generator::Derive;
22
23pub(crate) struct Features {
24    pub(crate) as_str_fn: FeatureAsStrFn,
25    pub(crate) debug_trait: FeatureDebugTrait,
26    pub(crate) display_trait: FeatureDisplayTrait,
27    pub(crate) from_str_fn: FeatureFromStrFn,
28    pub(crate) from_str_trait: FeatureFromStrTrait,
29    pub(crate) into_fn: FeatureIntoFn,
30    pub(crate) into_str_trait: FeatureIntoStrTrait,
31    pub(crate) into_trait: FeatureIntoTrait,
32    pub(crate) iter: FeatureIter,
33    pub(crate) max_const: FeatureMaxConst,
34    pub(crate) min_const: FeatureMinConst,
35    pub(crate) names: FeatureNames,
36    pub(crate) next_back_fn: FeatureNextBackFn,
37    pub(crate) next_fn: FeatureNextFn,
38    pub(crate) range_fn: FeatureRangeFn,
39    pub(crate) table_enum: FeatureTableEnum,
40    pub(crate) table_name: FeatureTableName,
41    pub(crate) table_range: FeatureTableRange,
42    pub(crate) try_from_fn: FeatureTryFromFn,
43    pub(crate) try_from_trait: FeatureTryFromTrait,
44}
45
46impl Features {
47    pub(crate) fn resolve(&mut self, derive: &Derive) {
48        self.resolve_enable(derive);
49        self.resolve_auto(derive);
50        self.resolve_enable(derive);
51    }
52
53    fn resolve_auto(&mut self, derive: &Derive) {
54        if [
55            self.as_str_fn.enabled && self.as_str_fn.mode == AsStrMode::Auto,
56            self.from_str_trait.enabled && self.from_str_trait.mode == FromStrMode::Auto,
57            self.from_str_fn.enabled && self.from_str_fn.mode == FromStrFnMode::Auto,
58        ]
59        .into_iter()
60        .filter(|b| *b)
61        .count()
62            > 1
63        {
64            self.table_name.enabled = true;
65        }
66
67        let table_enum = self.table_enum.enabled;
68        let table_name = self.table_name.enabled;
69
70        if self.as_str_fn.enabled && self.as_str_fn.mode == AsStrMode::Auto {
71            if table_name {
72                self.as_str_fn.mode = AsStrMode::Table;
73            } else {
74                self.as_str_fn.mode = AsStrMode::Match;
75            }
76        }
77
78        if self.from_str_trait.enabled && self.from_str_trait.mode == FromStrMode::Auto {
79            if table_name {
80                self.from_str_trait.mode = FromStrMode::Table;
81            } else {
82                self.from_str_trait.mode = FromStrMode::Match;
83            }
84        }
85
86        if self.from_str_fn.enabled && self.from_str_fn.mode == FromStrFnMode::Auto {
87            if table_name {
88                self.from_str_fn.mode = FromStrFnMode::Table;
89            } else {
90                self.from_str_fn.mode = FromStrFnMode::Match;
91            }
92        }
93
94        if self.iter.enabled && self.iter.mode == IterMode::Auto {
95            if derive.mode.is_gapless() {
96                self.iter.mode = IterMode::Range;
97            } else {
98                // has holes
99                if table_enum {
100                    self.iter.mode = IterMode::Table;
101                } else if derive.num_values * derive.repr_size_guessed <= 8
102                    && !self.range_fn.enabled
103                {
104                    self.iter.mode = IterMode::TableInline;
105                } else {
106                    self.iter.mode = IterMode::NextAndBack;
107                }
108            }
109        }
110    }
111
112    fn resolve_enable(&mut self, derive: &Derive) {
113        let mut features2 = Features2 {
114            as_str_fn: &mut self.as_str_fn,
115            iter: &mut self.iter,
116            min_const: &mut self.min_const,
117            max_const: &mut self.max_const,
118            next_fn: &mut self.next_fn,
119            next_back_fn: &mut self.next_back_fn,
120            table_enum: &mut self.table_enum,
121            table_name: &mut self.table_name,
122            table_range: &mut self.table_range,
123        };
124        self.debug_trait.check(&mut features2);
125        self.display_trait.check(&mut features2);
126        self.into_str_trait.check(&mut features2);
127        self.range_fn.check(derive, &mut features2);
128
129        let mut features1 = Features1 {
130            min_const: features2.min_const,
131            max_const: features2.max_const,
132            next_fn: features2.next_fn,
133            next_back_fn: features2.next_back_fn,
134            table_enum: features2.table_enum,
135            table_name: features2.table_name,
136            table_range: features2.table_range,
137        };
138        features2.as_str_fn.check(derive, &mut features1);
139        self.from_str_trait.check(derive, &mut features1);
140        self.from_str_fn.check(derive, &mut features1);
141        features2.iter.check(derive, &mut features1);
142        self.names.check(&mut features1);
143
144        let mut features0 = Features0 {
145            min_const: features1.min_const,
146            max_const: features1.max_const,
147            table_range: features1.table_range,
148        };
149        features1.next_fn.check(&mut features0);
150        features1.next_back_fn.check(&mut features0);
151        self.try_from_trait.check(&mut features0);
152        self.try_from_fn.check(&mut features0);
153
154        // totally stand-alone
155        self.into_trait.check();
156        self.into_fn.check();
157        features0.min_const.check();
158        features0.max_const.check();
159        features1.table_enum.check();
160        features1.table_name.check();
161        features0.table_range.check();
162    }
163}
164
165pub(crate) struct Features0<'a> {
166    pub(crate) max_const: &'a mut FeatureMaxConst,
167    pub(crate) min_const: &'a mut FeatureMinConst,
168    pub(crate) table_range: &'a mut FeatureTableRange,
169}
170
171pub(crate) struct Features1<'a> {
172    pub(crate) max_const: &'a mut FeatureMaxConst,
173    pub(crate) min_const: &'a mut FeatureMinConst,
174    pub(crate) next_fn: &'a mut FeatureNextFn,
175    pub(crate) next_back_fn: &'a mut FeatureNextBackFn,
176    pub(crate) table_enum: &'a mut FeatureTableEnum,
177    pub(crate) table_name: &'a mut FeatureTableName,
178    pub(crate) table_range: &'a mut FeatureTableRange,
179}
180
181pub(crate) struct Features2<'a> {
182    pub(crate) as_str_fn: &'a mut FeatureAsStrFn,
183    pub(crate) iter: &'a mut FeatureIter,
184    pub(crate) max_const: &'a mut FeatureMaxConst,
185    pub(crate) min_const: &'a mut FeatureMinConst,
186    pub(crate) next_fn: &'a mut FeatureNextFn,
187    pub(crate) next_back_fn: &'a mut FeatureNextBackFn,
188    pub(crate) table_enum: &'a mut FeatureTableEnum,
189    pub(crate) table_name: &'a mut FeatureTableName,
190    pub(crate) table_range: &'a mut FeatureTableRange,
191}