https://github.com/nvzqz/condtype
Choose Rust types at compile-time via constants
https://github.com/nvzqz/condtype
conditional rust types
Last synced: 10 months ago
JSON representation
Choose Rust types at compile-time via constants
- Host: GitHub
- URL: https://github.com/nvzqz/condtype
- Owner: nvzqz
- License: apache-2.0
- Created: 2023-04-18T19:45:18.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-01-23T15:00:50.000Z (about 2 years ago)
- Last Synced: 2024-05-09T15:28:58.192Z (over 1 year ago)
- Topics: conditional, rust, types
- Language: Rust
- Homepage: https://docs.rs/condtype
- Size: 46.9 KB
- Stars: 58
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# `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 = "hello";
let int: CondType = 42;
// Unsized types are also supported:
let str: &CondType = "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
[Option]\<[rlim_t][resource.h]> 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_t>;
const RLIM_NONE: RlimOption = condval!(if RLIM_INFINITY_IS_MAX {
None::
} else {
rlim_t::MAX
});
// Convert from either `RlimOption` type to `Option` via the `Into` trait:
let rlim_none: Option = 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;
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() {
let val: CondType = 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