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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
# `condtype`
[](https://docs.rs/condtype) [](https://crates.io/crates/condtype) [][github]
Choose Rust types at compile-time via boolean constants, brought to you by
[Nikolai Vazquez](https://hachyderm.io/@nikolai).
If you find this library useful, consider
[starring it][github] as well as
[sponsoring](https://github.com/sponsors/nvzqz) or
[donating once](https://paypal.me/nvzqz). 💖
[github]: https://github.com/nvzqz/condtype
## Conditional Typing
The [`CondType`] type and [`condval!`] macro choose types at compile-time using
[`bool`] constants, just like [`std::conditional_t` in C++](https://en.cppreference.com/w/cpp/types/conditional).
Unlike the [`Either`] type, the type chosen by [`CondType`]/[`condval!`] is
directly used, rather than wrapped with an [`enum`] type. This may be considered
a form of [dependent typing](https://en.wikipedia.org/wiki/Dependent_type), but
it is limited in ability and is restricted to compile-time constants rather than
runtime values.
## `CondType`
In the following example, [`CondType`] aliases either [`&str`] or [`i32`],
depending on the boolean [generic constant][const-generics]:
```rust
use condtype::CondType;
let str: CondType<true, &str, i32> = "hello";
let int: CondType<false, &str, i32> = 42;
// Unsized types are also supported:
let str: &CondType<true, str, [u8]> = "world";
```
## `condval!`
[`condval!`] enables choosing differently-typed values without specifying types.
In the following example, `val` is inferred to be either [`&str`] or [`i32`],
depending on `COND`.
```rust
use condtype::condval;
const COND: bool = true;
let val = condval!(if COND {
"hello"
} else {
42
});
assert_eq!(val, "hello");
```
`if let` pattern matching is also supported:
```rust
use condtype::condval;
const STR: Option<&str> = Some("hello");
let val = condval!(if let Some(str) = STR {
str.to_uppercase()
} else {
42
});
assert_eq!(val, "HELLO");
```
### Platform-Specific Types
This library can make code for some platforms more efficient by using
smaller-sized types, depending on platform-specific constants.
In the following example, the `RlimOption` type can be either
<code>[Option]\<[rlim_t][resource.h]></code> or [`rlim_t`][resource.h] itself,
where [`rlim_t::MAX`] can be treated as a sentinel value for
[`Option::None`][None] if it is not equal to [`RLIM_INFINITY`][resource.h].
```rust
use condtype::{condval, CondType};
use libc::{rlim_t, RLIM_INFINITY};
const RLIM_INFINITY_IS_MAX: bool = RLIM_INFINITY == rlim_t::MAX;
type RlimOption = CondType<RLIM_INFINITY_IS_MAX, Option<rlim_t>, rlim_t>;
const RLIM_NONE: RlimOption = condval!(if RLIM_INFINITY_IS_MAX {
None::<rlim_t>
} else {
rlim_t::MAX
});
// Convert from either `RlimOption` type to `Option` via the `Into` trait:
let rlim_none: Option<rlim_t> = RLIM_NONE.into();
```
Without this library, one could otherwise use [`cfg_if!`] to achieve the same
goal. However, using [`#[cfg]`][cfg] requires maintaining a list of platforms
and being more fine-grained if [`RLIM_INFINITY`][resource.h] is dependent on CPU
architecture.
```rust
use cfg_if::cfg_if;
use libc::rlim_t;
cfg_if! {
// Platforms where `RLIM_INFINITY != rlim_t::MAX`:
if #[cfg(any(
target_os = "macos",
target_os = "freebsd",
target_os = "solaris",
// ad nauseam...
))] {
type RlimOption = rlim_t;
const RLIM_NONE: RlimOption = rlim_t::MAX;
} else {
type RlimOption = Option<rlim_t>;
const RLIM_NONE: RlimOption = None;
}
}
```
## Limitations
It is currently not possible to use [`CondType`] or [`condval!`] with a
[generic constant][const-generics] because [Rust does not yet consider trait
implementations based on booleans to be exhaustive](https://github.com/rust-lang/project-const-generics/issues/26).
Once that issue is resolved, all versions of this library should _just work_
with generic constants.
```rust,ignore
fn generic<const B: bool>() {
let val: CondType<B, &str, i32> = condval!(if B {
"hello"
} else {
42
});
}
```
## Install
This library is [available on crates.io](https://crates.io/crates/condtype) and
can be used by running the following `cargo` command in your project directory:
```sh
cargo add condtype
```
or by manually adding the following to your project's [`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html):
```toml
[dependencies]
condtype = "1.3.0"
```
## License
Like the Rust project, this library may be used under either the
[MIT License](https://github.com/nvzqz/condtype/blob/main/LICENSE-MIT) or
[Apache License (Version 2.0)](https://github.com/nvzqz/condtype/blob/main/LICENSE-APACHE).
[`CondType`]: https://docs.rs/condtype/latest/condtype/type.CondType.html
[`condval!`]: https://docs.rs/condtype/latest/condtype/macro.condval.html
[`Either`]: https://docs.rs/either/latest/either/enum.Either.html
[`cfg_if!`]: https://docs.rs/cfg-if/latest/cfg_if/macro.cfg_if.html
[`const`]: https://doc.rust-lang.org/std/keyword.const.html
[`enum`]: https://doc.rust-lang.org/std/keyword.enum.html
[`bool`]: https://doc.rust-lang.org/std/primitive.bool.html
[`i32`]: https://doc.rust-lang.org/std/primitive.i32.html
[`&str`]: https://doc.rust-lang.org/std/primitive.str.html
[Option]: https://doc.rust-lang.org/std/option/enum.Option.html
[None]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
[cfg]: https://doc.rust-lang.org/rust-by-example/attribute/cfg.html
[`rlim_t::MAX`]: https://doc.rust-lang.org/std/primitive.u64.html#associatedconstant.MAX
[const-generics]: https://doc.rust-lang.org/reference/items/generics.html#const-generics
[resource.h]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_resource.h.html
|