1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Representation of a `#[doc(cfg(...))]` attribute.
13 // FIXME: Once RFC #1868 is implemented, switch to use those structures instead.
16 use std
::fmt
::{self, Write}
;
19 use std
::ascii
::AsciiExt
;
21 use syntax
::symbol
::Symbol
;
22 use syntax
::ast
::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, LitKind}
;
23 use syntax
::parse
::ParseSess
;
24 use syntax
::feature_gate
::Features
;
28 use html
::escape
::Escape
;
30 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, PartialEq)]
32 /// Accepts all configurations.
34 /// Denies all configurations.
36 /// A generic configration option, e.g. `test` or `target_os = "linux"`.
37 Cfg(Symbol
, Option
<Symbol
>),
38 /// Negate a configuration requirement, i.e. `not(x)`.
40 /// Union of a list of configuration requirements, i.e. `any(...)`.
42 /// Intersection of a list of configuration requirements, i.e. `all(...)`.
46 #[derive(PartialEq, Debug)]
47 pub struct InvalidCfgError
{
48 pub msg
: &'
static str,
53 /// Parses a `NestedMetaItem` into a `Cfg`.
54 fn parse_nested(nested_cfg
: &NestedMetaItem
) -> Result
<Cfg
, InvalidCfgError
> {
55 match nested_cfg
.node
{
56 NestedMetaItemKind
::MetaItem(ref cfg
) => Cfg
::parse(cfg
),
57 NestedMetaItemKind
::Literal(ref lit
) => Err(InvalidCfgError
{
58 msg
: "unexpected literal",
64 /// Parses a `MetaItem` into a `Cfg`.
66 /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g. `unix` or
67 /// `target_os = "redox"`.
69 /// If the content is not properly formatted, it will return an error indicating what and where
71 pub fn parse(cfg
: &MetaItem
) -> Result
<Cfg
, InvalidCfgError
> {
72 let name
= cfg
.name();
74 MetaItemKind
::Word
=> Ok(Cfg
::Cfg(name
, None
)),
75 MetaItemKind
::NameValue(ref lit
) => match lit
.node
{
76 LitKind
::Str(value
, _
) => Ok(Cfg
::Cfg(name
, Some(value
))),
77 _
=> Err(InvalidCfgError
{
78 // FIXME: if the main #[cfg] syntax decided to support non-string literals,
79 // this should be changed as well.
80 msg
: "value of cfg option should be a string literal",
84 MetaItemKind
::List(ref items
) => {
85 let mut sub_cfgs
= items
.iter().map(Cfg
::parse_nested
);
86 match &*name
.as_str() {
87 "all" => sub_cfgs
.fold(Ok(Cfg
::True
), |x
, y
| Ok(x?
& y?
)),
88 "any" => sub_cfgs
.fold(Ok(Cfg
::False
), |x
, y
| Ok(x?
| y?
)),
89 "not" => if sub_cfgs
.len() == 1 {
90 Ok(!sub_cfgs
.next().unwrap()?
)
93 msg
: "expected 1 cfg-pattern",
97 _
=> Err(InvalidCfgError
{
98 msg
: "invalid predicate",
106 /// Checks whether the given configuration can be matched in the current session.
108 /// Equivalent to `attr::cfg_matches`.
109 // FIXME: Actually make use of `features`.
110 pub fn matches(&self, parse_sess
: &ParseSess
, features
: Option
<&Features
>) -> bool
{
114 Cfg
::Not(ref child
) => !child
.matches(parse_sess
, features
),
115 Cfg
::All(ref sub_cfgs
) => {
116 sub_cfgs
.iter().all(|sub_cfg
| sub_cfg
.matches(parse_sess
, features
))
118 Cfg
::Any(ref sub_cfgs
) => {
119 sub_cfgs
.iter().any(|sub_cfg
| sub_cfg
.matches(parse_sess
, features
))
121 Cfg
::Cfg(name
, value
) => parse_sess
.config
.contains(&(name
, value
)),
125 /// Whether the configuration consists of just `Cfg` or `Not`.
126 fn is_simple(&self) -> bool
{
128 Cfg
::False
| Cfg
::True
| Cfg
::Cfg(..) | Cfg
::Not(..) => true,
129 Cfg
::All(..) | Cfg
::Any(..) => false,
133 /// Whether the configuration consists of just `Cfg`, `Not` or `All`.
134 fn is_all(&self) -> bool
{
136 Cfg
::False
| Cfg
::True
| Cfg
::Cfg(..) | Cfg
::Not(..) | Cfg
::All(..) => true,
137 Cfg
::Any(..) => false,
141 /// Renders the configuration for human display, as a short HTML description.
142 pub(crate) fn render_short_html(&self) -> String
{
143 let mut msg
= Html(self).to_string();
144 if self.should_capitalize_first_letter() {
145 if let Some(i
) = msg
.find(|c
: char| c
.is_ascii_alphanumeric()) {
146 msg
[i
.. i
+1].make_ascii_uppercase();
152 /// Renders the configuration for long display, as a long HTML description.
153 pub(crate) fn render_long_html(&self) -> String
{
154 let mut msg
= format
!("This is supported on <strong>{}</strong>", Html(self));
155 if self.should_append_only_to_description() {
156 msg
.push_str(" only");
162 fn should_capitalize_first_letter(&self) -> bool
{
164 Cfg
::False
| Cfg
::True
| Cfg
::Not(..) => true,
165 Cfg
::Any(ref sub_cfgs
) | Cfg
::All(ref sub_cfgs
) => {
166 sub_cfgs
.first().map(Cfg
::should_capitalize_first_letter
).unwrap_or(false)
168 Cfg
::Cfg(name
, _
) => match &*name
.as_str() {
169 "debug_assertions" | "target_endian" => true,
175 fn should_append_only_to_description(&self) -> bool
{
177 Cfg
::False
| Cfg
::True
=> false,
178 Cfg
::Any(..) | Cfg
::All(..) | Cfg
::Cfg(..) => true,
179 Cfg
::Not(ref child
) => match **child
{
180 Cfg
::Cfg(..) => true,
187 impl ops
::Not
for Cfg
{
189 fn not(self) -> Cfg
{
191 Cfg
::False
=> Cfg
::True
,
192 Cfg
::True
=> Cfg
::False
,
193 Cfg
::Not(cfg
) => *cfg
,
194 s
=> Cfg
::Not(Box
::new(s
)),
199 impl ops
::BitAndAssign
for Cfg
{
200 fn bitand_assign(&mut self, other
: Cfg
) {
201 match (self, other
) {
202 (&mut Cfg
::False
, _
) | (_
, Cfg
::True
) => {}
,
203 (s
, Cfg
::False
) => *s
= Cfg
::False
,
204 (s @
&mut Cfg
::True
, b
) => *s
= b
,
205 (&mut Cfg
::All(ref mut a
), Cfg
::All(ref mut b
)) => a
.append(b
),
206 (&mut Cfg
::All(ref mut a
), ref mut b
) => a
.push(mem
::replace(b
, Cfg
::True
)),
207 (s
, Cfg
::All(mut a
)) => {
208 let b
= mem
::replace(s
, Cfg
::True
);
213 let a
= mem
::replace(s
, Cfg
::True
);
214 *s
= Cfg
::All(vec
![a
, b
]);
220 impl ops
::BitAnd
for Cfg
{
222 fn bitand(mut self, other
: Cfg
) -> Cfg
{
228 impl ops
::BitOrAssign
for Cfg
{
229 fn bitor_assign(&mut self, other
: Cfg
) {
230 match (self, other
) {
231 (&mut Cfg
::True
, _
) | (_
, Cfg
::False
) => {}
,
232 (s
, Cfg
::True
) => *s
= Cfg
::True
,
233 (s @
&mut Cfg
::False
, b
) => *s
= b
,
234 (&mut Cfg
::Any(ref mut a
), Cfg
::Any(ref mut b
)) => a
.append(b
),
235 (&mut Cfg
::Any(ref mut a
), ref mut b
) => a
.push(mem
::replace(b
, Cfg
::True
)),
236 (s
, Cfg
::Any(mut a
)) => {
237 let b
= mem
::replace(s
, Cfg
::True
);
242 let a
= mem
::replace(s
, Cfg
::True
);
243 *s
= Cfg
::Any(vec
![a
, b
]);
249 impl ops
::BitOr
for Cfg
{
251 fn bitor(mut self, other
: Cfg
) -> Cfg
{
257 struct Html
<'a
>(&'a Cfg
);
259 fn write_with_opt_paren
<T
: fmt
::Display
>(
260 fmt
: &mut fmt
::Formatter
,
265 fmt
.write_char('
('
)?
;
269 fmt
.write_char('
)'
)?
;
275 impl<'a
> fmt
::Display
for Html
<'a
> {
276 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
278 Cfg
::Not(ref child
) => match **child
{
279 Cfg
::Any(ref sub_cfgs
) => {
280 let separator
= if sub_cfgs
.iter().all(Cfg
::is_simple
) {
285 for (i
, sub_cfg
) in sub_cfgs
.iter().enumerate() {
286 fmt
.write_str(if i
== 0 { "neither " }
else { separator }
)?
;
287 write_with_opt_paren(fmt
, !sub_cfg
.is_all(), Html(sub_cfg
))?
;
291 ref simple @ Cfg
::Cfg(..) => write
!(fmt
, "non-{}", Html(simple
)),
292 ref c
=> write
!(fmt
, "not ({})", Html(c
)),
295 Cfg
::Any(ref sub_cfgs
) => {
296 let separator
= if sub_cfgs
.iter().all(Cfg
::is_simple
) {
301 for (i
, sub_cfg
) in sub_cfgs
.iter().enumerate() {
303 fmt
.write_str(separator
)?
;
305 write_with_opt_paren(fmt
, !sub_cfg
.is_all(), Html(sub_cfg
))?
;
310 Cfg
::All(ref sub_cfgs
) => {
311 for (i
, sub_cfg
) in sub_cfgs
.iter().enumerate() {
313 fmt
.write_str(" and ")?
;
315 write_with_opt_paren(fmt
, !sub_cfg
.is_simple(), Html(sub_cfg
))?
;
320 Cfg
::True
=> fmt
.write_str("everywhere"),
321 Cfg
::False
=> fmt
.write_str("nowhere"),
323 Cfg
::Cfg(name
, value
) => {
324 let n
= &*name
.as_str();
325 let human_readable
= match (n
, value
) {
326 ("unix", None
) => "Unix",
327 ("windows", None
) => "Windows",
328 ("debug_assertions", None
) => "debug-assertions enabled",
329 ("target_os", Some(os
)) => match &*os
.as_str() {
330 "android" => "Android",
331 "bitrig" => "Bitrig",
332 "dragonfly" => "DragonFly BSD",
333 "emscripten" => "Emscripten",
334 "freebsd" => "FreeBSD",
335 "fuchsia" => "Fuchsia",
341 "netbsd" => "NetBSD",
342 "openbsd" => "OpenBSD",
344 "solaris" => "Solaris",
345 "windows" => "Windows",
348 ("target_arch", Some(arch
)) => match &*arch
.as_str() {
349 "aarch64" => "AArch64",
353 "mips64" => "MIPS-64",
354 "msp430" => "MSP430",
355 "powerpc" => "PowerPC",
356 "powerpc64" => "PowerPC-64",
358 "sparc64" => "SPARC64",
359 "wasm32" => "WebAssembly",
361 "x86_64" => "x86-64",
364 ("target_vendor", Some(vendor
)) => match &*vendor
.as_str() {
367 "rumprun" => "Rumprun",
371 ("target_env", Some(env
)) => match &*env
.as_str() {
375 "newlib" => "Newlib",
376 "uclibc" => "uClibc",
379 ("target_endian", Some(endian
)) => return write
!(fmt
, "{}-endian", endian
),
380 ("target_pointer_width", Some(bits
)) => return write
!(fmt
, "{}-bit", bits
),
383 if !human_readable
.is_empty() {
384 fmt
.write_str(human_readable
)
385 } else if let Some(v
) = value
{
386 write
!(fmt
, "<code>{}=\"{}\"</code>", Escape(n
), Escape(&*v
.as_str()))
388 write
!(fmt
, "<code>{}</code>", Escape(n
))
399 use syntax
::symbol
::Symbol
;
401 use syntax
::codemap
::dummy_spanned
;
402 use syntax_pos
::DUMMY_SP
;
404 fn word_cfg(s
: &str) -> Cfg
{
405 Cfg
::Cfg(Symbol
::intern(s
), None
)
408 fn name_value_cfg(name
: &str, value
: &str) -> Cfg
{
409 Cfg
::Cfg(Symbol
::intern(name
), Some(Symbol
::intern(value
)))
414 assert_eq
!(!Cfg
::False
, Cfg
::True
);
415 assert_eq
!(!Cfg
::True
, Cfg
::False
);
416 assert_eq
!(!word_cfg("test"), Cfg
::Not(Box
::new(word_cfg("test"))));
418 !Cfg
::All(vec
![word_cfg("a"), word_cfg("b")]),
419 Cfg
::Not(Box
::new(Cfg
::All(vec
![word_cfg("a"), word_cfg("b")])))
422 !Cfg
::Any(vec
![word_cfg("a"), word_cfg("b")]),
423 Cfg
::Not(Box
::new(Cfg
::Any(vec
![word_cfg("a"), word_cfg("b")])))
425 assert_eq
!(!Cfg
::Not(Box
::new(word_cfg("test"))), word_cfg("test"));
430 let mut x
= Cfg
::False
;
432 assert_eq
!(x
, Cfg
::False
);
434 x
= word_cfg("test");
436 assert_eq
!(x
, Cfg
::False
);
438 x
= word_cfg("test2");
440 assert_eq
!(x
, word_cfg("test2"));
443 x
&= word_cfg("test3");
444 assert_eq
!(x
, word_cfg("test3"));
446 x
&= word_cfg("test4");
447 assert_eq
!(x
, Cfg
::All(vec
![word_cfg("test3"), word_cfg("test4")]));
449 x
&= word_cfg("test5");
450 assert_eq
!(x
, Cfg
::All(vec
![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
452 x
&= Cfg
::All(vec
![word_cfg("test6"), word_cfg("test7")]);
453 assert_eq
!(x
, Cfg
::All(vec
![
461 let mut y
= Cfg
::Any(vec
![word_cfg("a"), word_cfg("b")]);
463 assert_eq
!(y
, Cfg
::All(vec
![
469 Cfg
::Any(vec
![word_cfg("a"), word_cfg("b")]),
473 word_cfg("a") & word_cfg("b") & word_cfg("c"),
474 Cfg
::All(vec
![word_cfg("a"), word_cfg("b"), word_cfg("c")])
480 let mut x
= Cfg
::True
;
482 assert_eq
!(x
, Cfg
::True
);
484 x
= word_cfg("test");
486 assert_eq
!(x
, Cfg
::True
);
488 x
= word_cfg("test2");
490 assert_eq
!(x
, word_cfg("test2"));
493 x
|= word_cfg("test3");
494 assert_eq
!(x
, word_cfg("test3"));
496 x
|= word_cfg("test4");
497 assert_eq
!(x
, Cfg
::Any(vec
![word_cfg("test3"), word_cfg("test4")]));
499 x
|= word_cfg("test5");
500 assert_eq
!(x
, Cfg
::Any(vec
![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
502 x
|= Cfg
::Any(vec
![word_cfg("test6"), word_cfg("test7")]);
503 assert_eq
!(x
, Cfg
::Any(vec
![
511 let mut y
= Cfg
::All(vec
![word_cfg("a"), word_cfg("b")]);
513 assert_eq
!(y
, Cfg
::Any(vec
![
519 Cfg
::All(vec
![word_cfg("a"), word_cfg("b")]),
523 word_cfg("a") | word_cfg("b") | word_cfg("c"),
524 Cfg
::Any(vec
![word_cfg("a"), word_cfg("b"), word_cfg("c")])
531 name
: Symbol
::intern("all"),
532 node
: MetaItemKind
::Word
,
535 assert_eq
!(Cfg
::parse(&mi
), Ok(word_cfg("all")));
538 name
: Symbol
::intern("all"),
539 node
: MetaItemKind
::NameValue(dummy_spanned(LitKind
::Str(
540 Symbol
::intern("done"),
545 assert_eq
!(Cfg
::parse(&mi
), Ok(name_value_cfg("all", "done")));
548 name
: Symbol
::intern("all"),
549 node
: MetaItemKind
::List(vec
![
550 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
551 name
: Symbol
::intern("a"),
552 node
: MetaItemKind
::Word
,
555 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
556 name
: Symbol
::intern("b"),
557 node
: MetaItemKind
::Word
,
563 assert_eq
!(Cfg
::parse(&mi
), Ok(word_cfg("a") & word_cfg("b")));
566 name
: Symbol
::intern("any"),
567 node
: MetaItemKind
::List(vec
![
568 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
569 name
: Symbol
::intern("a"),
570 node
: MetaItemKind
::Word
,
573 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
574 name
: Symbol
::intern("b"),
575 node
: MetaItemKind
::Word
,
581 assert_eq
!(Cfg
::parse(&mi
), Ok(word_cfg("a") | word_cfg("b")));
584 name
: Symbol
::intern("not"),
585 node
: MetaItemKind
::List(vec
![
586 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
587 name
: Symbol
::intern("a"),
588 node
: MetaItemKind
::Word
,
594 assert_eq
!(Cfg
::parse(&mi
), Ok(!word_cfg("a")));
597 name
: Symbol
::intern("not"),
598 node
: MetaItemKind
::List(vec
![
599 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
600 name
: Symbol
::intern("any"),
601 node
: MetaItemKind
::List(vec
![
602 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
603 name
: Symbol
::intern("a"),
604 node
: MetaItemKind
::Word
,
607 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
608 name
: Symbol
::intern("all"),
609 node
: MetaItemKind
::List(vec
![
610 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
611 name
: Symbol
::intern("b"),
612 node
: MetaItemKind
::Word
,
615 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
616 name
: Symbol
::intern("c"),
617 node
: MetaItemKind
::Word
,
629 assert_eq
!(Cfg
::parse(&mi
), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
632 name
: Symbol
::intern("all"),
633 node
: MetaItemKind
::List(vec
![
634 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
635 name
: Symbol
::intern("a"),
636 node
: MetaItemKind
::Word
,
639 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
640 name
: Symbol
::intern("b"),
641 node
: MetaItemKind
::Word
,
644 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
645 name
: Symbol
::intern("c"),
646 node
: MetaItemKind
::Word
,
652 assert_eq
!(Cfg
::parse(&mi
), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c")));
656 fn test_parse_err() {
658 name
: Symbol
::intern("foo"),
659 node
: MetaItemKind
::NameValue(dummy_spanned(LitKind
::Bool(false))),
662 assert
!(Cfg
::parse(&mi
).is_err());
665 name
: Symbol
::intern("not"),
666 node
: MetaItemKind
::List(vec
![
667 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
668 name
: Symbol
::intern("a"),
669 node
: MetaItemKind
::Word
,
672 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
673 name
: Symbol
::intern("b"),
674 node
: MetaItemKind
::Word
,
680 assert
!(Cfg
::parse(&mi
).is_err());
683 name
: Symbol
::intern("not"),
684 node
: MetaItemKind
::List(vec
![]),
687 assert
!(Cfg
::parse(&mi
).is_err());
690 name
: Symbol
::intern("foo"),
691 node
: MetaItemKind
::List(vec
![
692 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
693 name
: Symbol
::intern("a"),
694 node
: MetaItemKind
::Word
,
700 assert
!(Cfg
::parse(&mi
).is_err());
703 name
: Symbol
::intern("all"),
704 node
: MetaItemKind
::List(vec
![
705 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
706 name
: Symbol
::intern("foo"),
707 node
: MetaItemKind
::List(vec
![]),
710 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
711 name
: Symbol
::intern("b"),
712 node
: MetaItemKind
::Word
,
718 assert
!(Cfg
::parse(&mi
).is_err());
721 name
: Symbol
::intern("any"),
722 node
: MetaItemKind
::List(vec
![
723 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
724 name
: Symbol
::intern("a"),
725 node
: MetaItemKind
::Word
,
728 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
729 name
: Symbol
::intern("foo"),
730 node
: MetaItemKind
::List(vec
![]),
736 assert
!(Cfg
::parse(&mi
).is_err());
739 name
: Symbol
::intern("not"),
740 node
: MetaItemKind
::List(vec
![
741 dummy_spanned(NestedMetaItemKind
::MetaItem(MetaItem
{
742 name
: Symbol
::intern("foo"),
743 node
: MetaItemKind
::List(vec
![]),
749 assert
!(Cfg
::parse(&mi
).is_err());
753 fn test_render_short_html() {
755 word_cfg("unix").render_short_html(),
759 name_value_cfg("target_os", "macos").render_short_html(),
763 name_value_cfg("target_pointer_width", "16").render_short_html(),
767 name_value_cfg("target_endian", "little").render_short_html(),
771 (!word_cfg("windows")).render_short_html(),
775 (word_cfg("unix") & word_cfg("windows")).render_short_html(),
779 (word_cfg("unix") | word_cfg("windows")).render_short_html(),
784 word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions")
785 ).render_short_html(),
786 "Unix and Windows and debug-assertions enabled"
790 word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")
791 ).render_short_html(),
792 "Unix or Windows or debug-assertions enabled"
796 !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
797 ).render_short_html(),
798 "Neither Unix nor Windows nor debug-assertions enabled"
802 (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) |
803 (word_cfg("windows") & name_value_cfg("target_pointer_width", "64"))
804 ).render_short_html(),
805 "Unix and x86-64, or Windows and 64-bit"
808 (!(word_cfg("unix") & word_cfg("windows"))).render_short_html(),
809 "Not (Unix and Windows)"
813 (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix")
814 ).render_short_html(),
815 "(Debug-assertions enabled or Windows) and Unix"
820 fn test_render_long_html() {
822 word_cfg("unix").render_long_html(),
823 "This is supported on <strong>Unix</strong> only."
826 name_value_cfg("target_os", "macos").render_long_html(),
827 "This is supported on <strong>macOS</strong> only."
830 name_value_cfg("target_pointer_width", "16").render_long_html(),
831 "This is supported on <strong>16-bit</strong> only."
834 name_value_cfg("target_endian", "little").render_long_html(),
835 "This is supported on <strong>little-endian</strong> only."
838 (!word_cfg("windows")).render_long_html(),
839 "This is supported on <strong>non-Windows</strong> only."
842 (word_cfg("unix") & word_cfg("windows")).render_long_html(),
843 "This is supported on <strong>Unix and Windows</strong> only."
846 (word_cfg("unix") | word_cfg("windows")).render_long_html(),
847 "This is supported on <strong>Unix or Windows</strong> only."
851 word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions")
852 ).render_long_html(),
853 "This is supported on <strong>Unix and Windows and debug-assertions enabled</strong> \
858 word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")
859 ).render_long_html(),
860 "This is supported on <strong>Unix or Windows or debug-assertions enabled</strong> \
865 !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
866 ).render_long_html(),
867 "This is supported on <strong>neither Unix nor Windows nor debug-assertions \
872 (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) |
873 (word_cfg("windows") & name_value_cfg("target_pointer_width", "64"))
874 ).render_long_html(),
875 "This is supported on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
878 (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(),
879 "This is supported on <strong>not (Unix and Windows)</strong>."
883 (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix")
884 ).render_long_html(),
885 "This is supported on <strong>(debug-assertions enabled or Windows) and Unix</strong> \