1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
use crate::gen::{CfgEvaluator, CfgResult};
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::fmt::{self, Debug};
use syn::parse::ParseStream;
use syn::{Ident, LitBool, LitStr, Token};
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub(crate) enum CfgValue {
Bool(bool),
Str(String),
}
impl CfgValue {
const FALSE: Self = CfgValue::Bool(false);
const TRUE: Self = CfgValue::Bool(true);
}
pub(crate) struct FlagsCfgEvaluator {
map: Map<String, Set<CfgValue>>,
}
impl FlagsCfgEvaluator {
pub(crate) fn new(map: Map<String, Set<CfgValue>>) -> Self {
FlagsCfgEvaluator { map }
}
}
impl CfgEvaluator for FlagsCfgEvaluator {
fn eval(&self, name: &str, value: Option<&str>) -> CfgResult {
let set = self.map.get(name);
if let Some(value) = value {
if let Some(set) = set {
CfgResult::from(set.contains(&CfgValue::Str(value.to_owned())))
} else if name == "feature" {
CfgResult::False
} else {
let msg = format!(
"pass `--cfg {}=\"...\"` to be able to use this attribute",
name,
);
CfgResult::Undetermined { msg }
}
} else {
let (mut is_false, mut is_true) = (false, false);
if let Some(set) = set {
is_false = set.contains(&CfgValue::FALSE);
is_true = set.contains(&CfgValue::TRUE);
}
if is_false && is_true {
let msg = format!("the cxxbridge flags say both {0}=false and {0}=true", name);
CfgResult::Undetermined { msg }
} else if is_false {
CfgResult::False
} else if is_true {
CfgResult::True
} else {
let msg = format!(
"pass either `--cfg {0}=true` or `--cfg {0}=false` to be able to use this cfg attribute",
name,
);
CfgResult::Undetermined { msg }
}
}
}
}
impl Debug for CfgValue {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
CfgValue::Bool(value) => Debug::fmt(value, formatter),
CfgValue::Str(value) => Debug::fmt(value, formatter),
}
}
}
pub(crate) fn parse(input: ParseStream) -> syn::Result<(String, CfgValue)> {
let ident: Ident = input.parse()?;
let name = ident.to_string();
if input.is_empty() {
return Ok((name, CfgValue::TRUE));
}
input.parse::<Token![=]>()?;
let lookahead = input.lookahead1();
if lookahead.peek(LitBool) {
let lit: LitBool = input.parse()?;
Ok((name, CfgValue::Bool(lit.value)))
} else if lookahead.peek(LitStr) {
let lit: LitStr = input.parse()?;
Ok((name, CfgValue::Str(lit.value())))
} else {
Err(lookahead.error())
}
}
|