1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use std::collections::BTreeMap;
6 use std::mem;
7 
8 use crate::bindgen::config::Config;
9 use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
10 use crate::bindgen::dependencies::Dependencies;
11 use crate::bindgen::ir::{
12     AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
13 };
14 use crate::bindgen::library::Library;
15 use crate::bindgen::monomorph::Monomorphs;
16 
17 /// An item is any type of rust item besides a function
18 pub trait Item {
path(&self) -> &Path19     fn path(&self) -> &Path;
name(&self) -> &str20     fn name(&self) -> &str {
21         self.path().name()
22     }
export_name(&self) -> &str23     fn export_name(&self) -> &str {
24         self.name()
25     }
cfg(&self) -> Option<&Cfg>26     fn cfg(&self) -> Option<&Cfg>;
annotations(&self) -> &AnnotationSet27     fn annotations(&self) -> &AnnotationSet;
annotations_mut(&mut self) -> &mut AnnotationSet28     fn annotations_mut(&mut self) -> &mut AnnotationSet;
29 
container(&self) -> ItemContainer30     fn container(&self) -> ItemContainer;
31 
collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver)32     fn collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver) {
33         unimplemented!()
34     }
resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver)35     fn resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver) {
36         unimplemented!()
37     }
rename_for_config(&mut self, _config: &Config)38     fn rename_for_config(&mut self, _config: &Config) {}
add_dependencies(&self, _library: &Library, _out: &mut Dependencies)39     fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs)40     fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) {
41         unreachable!("Cannot instantiate {} as a generic.", self.name())
42     }
43 }
44 
45 #[derive(Debug, Clone)]
46 pub enum ItemContainer {
47     Constant(Constant),
48     Static(Static),
49     OpaqueItem(OpaqueItem),
50     Struct(Struct),
51     Union(Union),
52     Enum(Enum),
53     Typedef(Typedef),
54 }
55 
56 impl ItemContainer {
deref(&self) -> &dyn Item57     pub fn deref(&self) -> &dyn Item {
58         match *self {
59             ItemContainer::Constant(ref x) => x,
60             ItemContainer::Static(ref x) => x,
61             ItemContainer::OpaqueItem(ref x) => x,
62             ItemContainer::Struct(ref x) => x,
63             ItemContainer::Union(ref x) => x,
64             ItemContainer::Enum(ref x) => x,
65             ItemContainer::Typedef(ref x) => x,
66         }
67     }
68 }
69 
70 #[derive(Debug, Clone)]
71 pub enum ItemValue<T: Item> {
72     Cfg(Vec<T>),
73     Single(T),
74 }
75 
76 #[derive(Debug, Clone)]
77 pub struct ItemMap<T: Item> {
78     data: BTreeMap<Path, ItemValue<T>>,
79 }
80 
81 impl<T: Item + Clone> ItemMap<T> {
new() -> ItemMap<T>82     pub fn new() -> ItemMap<T> {
83         ItemMap {
84             data: BTreeMap::new(),
85         }
86     }
87 
rebuild(&mut self)88     pub fn rebuild(&mut self) {
89         let old = mem::replace(self, ItemMap::new());
90         old.for_all_items(|x| {
91             self.try_insert(x.clone());
92         });
93     }
94 
try_insert(&mut self, item: T) -> bool95     pub fn try_insert(&mut self, item: T) -> bool {
96         match (item.cfg().is_some(), self.data.get_mut(item.path())) {
97             (true, Some(&mut ItemValue::Cfg(ref mut items))) => {
98                 items.push(item);
99                 return true;
100             }
101             (false, Some(&mut ItemValue::Cfg(_))) => {
102                 return false;
103             }
104             (true, Some(&mut ItemValue::Single(_))) => {
105                 return false;
106             }
107             (false, Some(&mut ItemValue::Single(_))) => {
108                 return false;
109             }
110             _ => {}
111         }
112 
113         let path = item.path().clone();
114         if item.cfg().is_some() {
115             self.data.insert(path, ItemValue::Cfg(vec![item]));
116         } else {
117             self.data.insert(path, ItemValue::Single(item));
118         }
119 
120         true
121     }
122 
extend_with(&mut self, other: &ItemMap<T>)123     pub fn extend_with(&mut self, other: &ItemMap<T>) {
124         other.for_all_items(|x| {
125             self.try_insert(x.clone());
126         });
127     }
128 
to_vec(&self) -> Vec<T>129     pub fn to_vec(&self) -> Vec<T> {
130         let mut result = Vec::with_capacity(self.data.len());
131         for container in self.data.values() {
132             match *container {
133                 ItemValue::Cfg(ref items) => result.extend_from_slice(items),
134                 ItemValue::Single(ref item) => {
135                     result.push(item.clone());
136                 }
137             }
138         }
139         result
140     }
141 
get_items(&self, path: &Path) -> Option<Vec<ItemContainer>>142     pub fn get_items(&self, path: &Path) -> Option<Vec<ItemContainer>> {
143         Some(match *self.data.get(path)? {
144             ItemValue::Cfg(ref items) => items.iter().map(|x| x.container()).collect(),
145             ItemValue::Single(ref item) => vec![item.container()],
146         })
147     }
148 
filter<F>(&mut self, callback: F) where F: Fn(&T) -> bool,149     pub fn filter<F>(&mut self, callback: F)
150     where
151         F: Fn(&T) -> bool,
152     {
153         let data = mem::replace(&mut self.data, BTreeMap::new());
154 
155         for (name, container) in data {
156             match container {
157                 ItemValue::Cfg(items) => {
158                     let mut new_items = Vec::new();
159                     for item in items {
160                         if !callback(&item) {
161                             new_items.push(item);
162                         }
163                     }
164                     if !new_items.is_empty() {
165                         self.data.insert(name, ItemValue::Cfg(new_items));
166                     }
167                 }
168                 ItemValue::Single(item) => {
169                     if !callback(&item) {
170                         self.data.insert(name, ItemValue::Single(item));
171                     }
172                 }
173             }
174         }
175     }
176 
for_all_items<F>(&self, mut callback: F) where F: FnMut(&T),177     pub fn for_all_items<F>(&self, mut callback: F)
178     where
179         F: FnMut(&T),
180     {
181         for container in self.data.values() {
182             match *container {
183                 ItemValue::Cfg(ref items) => {
184                     for item in items {
185                         callback(item);
186                     }
187                 }
188                 ItemValue::Single(ref item) => callback(item),
189             }
190         }
191     }
192 
for_all_items_mut<F>(&mut self, mut callback: F) where F: FnMut(&mut T),193     pub fn for_all_items_mut<F>(&mut self, mut callback: F)
194     where
195         F: FnMut(&mut T),
196     {
197         for container in self.data.values_mut() {
198             match *container {
199                 ItemValue::Cfg(ref mut items) => {
200                     for item in items {
201                         callback(item);
202                     }
203                 }
204                 ItemValue::Single(ref mut item) => callback(item),
205             }
206         }
207     }
208 
for_items<F>(&self, path: &Path, mut callback: F) where F: FnMut(&T),209     pub fn for_items<F>(&self, path: &Path, mut callback: F)
210     where
211         F: FnMut(&T),
212     {
213         match self.data.get(path) {
214             Some(&ItemValue::Cfg(ref items)) => {
215                 for item in items {
216                     callback(item);
217                 }
218             }
219             Some(&ItemValue::Single(ref item)) => {
220                 callback(item);
221             }
222             None => {}
223         }
224     }
225 
for_items_mut<F>(&mut self, path: &Path, mut callback: F) where F: FnMut(&mut T),226     pub fn for_items_mut<F>(&mut self, path: &Path, mut callback: F)
227     where
228         F: FnMut(&mut T),
229     {
230         match self.data.get_mut(path) {
231             Some(&mut ItemValue::Cfg(ref mut items)) => {
232                 for item in items {
233                     callback(item);
234                 }
235             }
236             Some(&mut ItemValue::Single(ref mut item)) => {
237                 callback(item);
238             }
239             None => {}
240         }
241     }
242 }
243