guppy/platform/
platform_eval.rs1use crate::platform::{Platform, PlatformSpec};
5use std::ops::{BitAnd, BitOr};
6use target_spec::TargetSpec;
7
8#[derive(Copy, Clone, Debug)]
12pub enum PlatformStatus<'g> {
13 Never,
15 Always,
17 PlatformDependent {
19 eval: PlatformEval<'g>,
21 },
22}
23
24assert_covariant!(PlatformStatus);
25
26impl<'g> PlatformStatus<'g> {
27 pub(crate) fn new(specs: &'g PlatformStatusImpl) -> Self {
28 match specs {
29 PlatformStatusImpl::Always => PlatformStatus::Always,
30 PlatformStatusImpl::Specs(specs) => {
31 if specs.is_empty() {
32 PlatformStatus::Never
33 } else {
34 PlatformStatus::PlatformDependent {
35 eval: PlatformEval { specs },
36 }
37 }
38 }
39 }
40 }
41
42 pub fn is_always(&self) -> bool {
44 match self {
45 PlatformStatus::Always => true,
46 PlatformStatus::PlatformDependent { .. } | PlatformStatus::Never => false,
47 }
48 }
49
50 pub fn is_never(&self) -> bool {
52 match self {
53 PlatformStatus::Never => true,
54 PlatformStatus::PlatformDependent { .. } | PlatformStatus::Always => false,
55 }
56 }
57
58 pub fn is_present(&self) -> bool {
60 !self.is_never()
61 }
62
63 pub fn enabled_on(&self, platform_spec: &PlatformSpec) -> EnabledTernary {
68 match (self, platform_spec) {
69 (PlatformStatus::Always, _) => EnabledTernary::Enabled,
70 (PlatformStatus::Never, _) => EnabledTernary::Disabled,
71 (PlatformStatus::PlatformDependent { .. }, PlatformSpec::Any) => {
72 EnabledTernary::Enabled
73 }
74 (PlatformStatus::PlatformDependent { eval }, PlatformSpec::Platform(platform)) => {
75 eval.eval(platform)
76 }
77 (PlatformStatus::PlatformDependent { .. }, PlatformSpec::Always) => {
78 EnabledTernary::Disabled
79 }
80 }
81 }
82}
83
84#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
91pub enum EnabledTernary {
92 Disabled,
94 Unknown,
101 Enabled,
103}
104
105impl EnabledTernary {
106 fn new(x: Option<bool>) -> Self {
107 match x {
108 Some(false) => EnabledTernary::Disabled,
109 None => EnabledTernary::Unknown,
110 Some(true) => EnabledTernary::Enabled,
111 }
112 }
113
114 pub fn is_known(self) -> bool {
116 match self {
117 EnabledTernary::Disabled | EnabledTernary::Enabled => true,
118 EnabledTernary::Unknown => false,
119 }
120 }
121}
122
123impl BitAnd for EnabledTernary {
125 type Output = Self;
126
127 fn bitand(self, rhs: Self) -> Self::Output {
128 use EnabledTernary::*;
129
130 match (self, rhs) {
131 (Enabled, Enabled) => Enabled,
132 (Disabled, _) | (_, Disabled) => Disabled,
133 _ => Unknown,
134 }
135 }
136}
137
138impl BitOr for EnabledTernary {
140 type Output = Self;
141
142 fn bitor(self, rhs: Self) -> Self {
143 use EnabledTernary::*;
144
145 match (self, rhs) {
146 (Disabled, Disabled) => Disabled,
147 (Enabled, _) | (_, Enabled) => Enabled,
148 _ => Unknown,
149 }
150 }
151}
152
153#[derive(Copy, Clone, Debug)]
157pub struct PlatformEval<'g> {
158 specs: &'g [TargetSpec],
159}
160
161assert_covariant!(PlatformEval);
162
163impl<'g> PlatformEval<'g> {
164 pub fn eval(&self, platform: &Platform) -> EnabledTernary {
166 let mut res = EnabledTernary::Disabled;
167 for spec in self.specs.iter() {
168 let matches = spec.eval(platform);
169 if matches == Some(true) {
171 return EnabledTernary::Enabled;
172 }
173 res = res | EnabledTernary::new(matches);
174 }
175 res
176 }
177
178 pub fn target_specs(&self) -> &'g [TargetSpec] {
183 self.specs
184 }
185}
186
187#[derive(Clone, Debug)]
188pub(crate) enum PlatformStatusImpl {
189 Always,
190 Specs(Vec<TargetSpec>),
192}
193
194impl PlatformStatusImpl {
195 pub(crate) fn is_never(&self) -> bool {
197 match self {
198 PlatformStatusImpl::Always => false,
199 PlatformStatusImpl::Specs(specs) => specs.is_empty(),
200 }
201 }
202
203 pub(crate) fn extend(&mut self, other: &PlatformStatusImpl) {
204 match (&mut *self, other) {
206 (PlatformStatusImpl::Always, _) => {
207 }
209 (PlatformStatusImpl::Specs(_), PlatformStatusImpl::Always) => {
210 *self = PlatformStatusImpl::Always;
212 }
213 (PlatformStatusImpl::Specs(specs), PlatformStatusImpl::Specs(other)) => {
214 specs.extend_from_slice(other.as_slice());
215 }
216 }
217 }
218
219 pub(crate) fn add_spec(&mut self, spec: Option<&TargetSpec>) {
220 match (&mut *self, spec) {
222 (PlatformStatusImpl::Always, _) => {
223 }
225 (PlatformStatusImpl::Specs(_), None) => {
226 *self = PlatformStatusImpl::Always;
228 }
229 (PlatformStatusImpl::Specs(specs), Some(spec)) => {
230 specs.push(spec.clone());
231 }
232 }
233 }
234}
235
236impl Default for PlatformStatusImpl {
237 fn default() -> Self {
238 PlatformStatusImpl::Specs(vec![])
240 }
241}