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