midenc_hir/ir/effects/
interface.rs1use smallvec::SmallVec;
2
3use super::*;
4use crate::{SymbolRef, ValueRef};
5
6pub trait EffectOpInterface<T: Effect> {
7 fn effects(&self) -> EffectIterator<T>;
9 fn has_no_effect(&self) -> bool {
11 self.effects().is_empty()
12 }
13 fn effects_on_value(&self, value: ValueRef) -> ValueEffectIterator<T> {
15 EffectIterator::for_value(self.effects(), value)
16 }
17 fn effects_on_symbol(&self, symbol: SymbolRef) -> SymbolEffectIterator<T> {
19 EffectIterator::for_symbol(self.effects(), symbol)
20 }
21 fn effects_on_resource<'a, 'b: 'a>(
23 &self,
24 resource: &'b dyn Resource,
25 ) -> ResourceEffectIterator<'b, T> {
26 EffectIterator::for_resource(self.effects(), resource)
27 }
28}
29
30impl<T: Effect> dyn EffectOpInterface<T> {
31 pub fn effects_of_type<E>(&self) -> impl Iterator<Item = EffectInstance<T>> + '_
33 where
34 E: Effect,
35 {
36 self.effects().filter(|instance| (instance.effect() as &dyn Any).is::<E>())
37 }
38
39 pub fn has_effect<E>(&self) -> bool
41 where
42 E: Any,
43 {
44 self.effects().any(|instance| (instance.effect() as &dyn Any).is::<E>())
45 }
46
47 pub fn only_has_effect<E>(&self) -> bool
49 where
50 E: Any,
51 {
52 let mut effects = self.effects();
53 !effects.is_empty() && effects.all(|instance| (instance.effect() as &dyn Any).is::<E>())
54 }
55}
56
57pub struct EffectIterator<T> {
58 effects: smallvec::IntoIter<[EffectInstance<T>; 4]>,
59}
60impl<T> EffectIterator<T> {
61 pub fn from_smallvec(effects: SmallVec<[EffectInstance<T>; 4]>) -> Self {
62 Self {
63 effects: effects.into_iter(),
64 }
65 }
66
67 pub fn new(effects: impl IntoIterator<Item = EffectInstance<T>>) -> Self {
68 let effects = effects.into_iter().collect::<SmallVec<[_; 4]>>();
69 Self {
70 effects: effects.into_iter(),
71 }
72 }
73
74 pub const fn for_value(effects: Self, value: ValueRef) -> ValueEffectIterator<T> {
75 ValueEffectIterator {
76 iter: effects,
77 value,
78 }
79 }
80
81 pub const fn for_symbol(effects: Self, symbol: SymbolRef) -> SymbolEffectIterator<T> {
82 SymbolEffectIterator {
83 iter: effects,
84 symbol,
85 }
86 }
87
88 pub const fn for_resource(
89 effects: Self,
90 resource: &dyn Resource,
91 ) -> ResourceEffectIterator<'_, T> {
92 ResourceEffectIterator {
93 iter: effects,
94 resource,
95 }
96 }
97
98 #[inline]
99 pub fn as_slice(&self) -> &[EffectInstance<T>] {
100 self.effects.as_slice()
101 }
102}
103impl<T> core::iter::FusedIterator for EffectIterator<T> {}
104impl<T> ExactSizeIterator for EffectIterator<T> {
105 fn is_empty(&self) -> bool {
106 self.effects.is_empty()
107 }
108
109 fn len(&self) -> usize {
110 self.effects.len()
111 }
112}
113impl<T> Iterator for EffectIterator<T> {
114 type Item = EffectInstance<T>;
115
116 #[inline]
117 fn next(&mut self) -> Option<Self::Item> {
118 self.effects.next()
119 }
120}
121
122pub struct ValueEffectIterator<T> {
123 iter: EffectIterator<T>,
124 value: ValueRef,
125}
126impl<T> core::iter::FusedIterator for ValueEffectIterator<T> {}
127impl<T> Iterator for ValueEffectIterator<T> {
128 type Item = EffectInstance<T>;
129
130 fn next(&mut self) -> Option<Self::Item> {
131 while let Some(instance) = self.iter.next() {
132 if instance.value().is_some_and(|v| v == self.value) {
133 return Some(instance);
134 }
135 }
136
137 None
138 }
139}
140
141pub struct SymbolEffectIterator<T> {
142 iter: EffectIterator<T>,
143 symbol: SymbolRef,
144}
145impl<T> core::iter::FusedIterator for SymbolEffectIterator<T> {}
146impl<T> Iterator for SymbolEffectIterator<T> {
147 type Item = EffectInstance<T>;
148
149 fn next(&mut self) -> Option<Self::Item> {
150 while let Some(instance) = self.iter.next() {
151 if instance.symbol().is_some_and(|s| s == self.symbol) {
152 return Some(instance);
153 }
154 }
155
156 None
157 }
158}
159
160pub struct ResourceEffectIterator<'a, T> {
161 iter: EffectIterator<T>,
162 resource: &'a dyn Resource,
163}
164impl<T> core::iter::FusedIterator for ResourceEffectIterator<'_, T> {}
165impl<T> Iterator for ResourceEffectIterator<'_, T> {
166 type Item = EffectInstance<T>;
167
168 fn next(&mut self) -> Option<Self::Item> {
169 #[allow(clippy::while_let_on_iterator)]
170 while let Some(instance) = self.iter.next() {
171 if instance.resource().dyn_eq(self.resource) {
172 return Some(instance);
173 }
174 }
175
176 None
177 }
178}