Simple procedural macros `tnconst![...]`, `pconst![...]`, `nconst![...]` and `uconst![...]` that returns the type level integer from `typenum` crate.

Overview

typenum-consts

GitHub Workflow Status Crates.io Version docs.rs

Procedural macros that take a literal integer (or the result of an evaluation of simple mathematical expressions or an environment variable whose value is a literal integer) and convert it to a typenum::Unsigned / typenum::Integer type-level positive/negative/unsigned integer.

Why?

It saves time.

Assuming you want a type-level positive integer 84938493, tnconst![+84938493] outputs directly typenum::PInt<U84938493> (by the way, U84938493 does not exist in typenum::consts). The alternative is to type PInt<Sum<Prod<Exp<..., ...>, ...>, ...>, ...> (which argubly takes a lot more time).

Example:

# use core::marker::PhantomData;
# use typenum_consts::tnconst;
# use typenum::*;
#
# #[cfg(target_pointer_width = "32")]
# type I32OrI64 = i32;
# #[cfg(target_pointer_width = "64")]
# type I32OrI64 = i64;
type ActualPositive84938493Type = tnconst![+84938493];
type ExpectedPositive84938493Type = PInt< // `PInt` implies positive integer at the type level
Sum<
Prod<Exp<U10, U7>, U8>, // 10**7 * 8
Sum<
Prod<Exp<U10, U6>, U4>, // 10**6 * 4
Sum<
Prod<Exp<U10, U5>, U9>, // 10**5 * 9
Sum<
Prod<Exp<U10, U4>, U3>, // 10**4 * 3
Sum<
Prod<Exp<U10, U3>, U8>, // 10**3 * 8
Sum<
Prod<Exp<U10, U2>, U4>, // 10**2 * 4
Sum<
Prod<Exp<U10, U1>, U9>, // 10**1 * 9
Sum<
Prod<Exp<U10, U0>, U3>, // 10**0 * 3
U0>>>>>>>>
>;

typenum::assert_type_eq!(ExpectedPositive84938493Type, ActualPositive84938493Type);
assert_eq!(
    <ExpectedPositive84938493Type as typenum::ToInt<I32OrI64>>::INT,
    <ActualPositive84938493Type as typenum::ToInt<I32OrI64>>::INT
);

For conditional compilation.

Suppose in different environments you want a different type-level integer, you can either use e.g. #[cfg(production)] type NUMBER = U69; or you can do the following:

use typenum::{U69, assert_type_eq};
use typenum_consts::uconst;
// ``` .env
// ENV_VAR=69
// ```
type E = uconst![env!("ENV_VAR");];
assert_type_eq!(E, U69);

All four macros, namely, tnconst![...], pconst![...], uconst![...] and nconst![...], can read literal integers from the environment.

Three ways to use it

Take pconst![...] as the example (the rest of the macros work almost identically).

1. Invoke it with a literal integer

use typenum::{P123, assert_type_eq};
use typenum_consts::pconst;
type A = pconst![123];
assert_type_eq!(A, P123);

2. Invoke using an expression or many simple mathematical expressions

use typenum::{P15, assert_type_eq};
use typenum_consts::pconst;
type D = pconst![{
    a = 10;
    b = 5;
    a + b; // Last statement is always the final returned value to be casted into `typenum` type-level integer, P15
}];
assert_type_eq!(D, P15);

3. Invoke by reading from an environment variable

Note: env!(...) is a macro-like invocation. The first parameter is mandatory and is the key of the environment variable that pconst will read. The second parameter is optional and is the file path of the .env.* file to read the environment variable from, e.g. env!("ENV_VAR", "./.env.prod"), "ENV_VAR" is the key to read the value from and "./.env.prod" is the file path relative to CARGO_MANIFEST_DIR.

use typenum::{P69, assert_type_eq};
use typenum_consts::pconst;
// ``` .env
// ENV_VAR=69
// ```
type E = pconst![env!("ENV_VAR");];
assert_type_eq!(E, P69);

Roadmap

  • Feature gate evaluation of mathematical expressions and reading from environment variables.
  • Enable testing for Rust version 1.70.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
A memory efficient immutable string type that can store up to 24* bytes on the stack

compact_str A memory efficient immutable string type that can store up to 24* bytes on the stack. * 12 bytes for 32-bit architectures About A CompactS

An annotated string type in Rust, made up of string slices

A string type made up of multiple annotated string slices.

Type-safe IPC for Tauri using GraphQL

Tauri Plugin graphql A plugin for Tauri that enables type-safe IPC through GraphQL. Install Rust [dependencies] tauri-plugin-graphql = "0.2" JavaScrip

The most fundamental type for async synchronization: an intrusive linked list of futures

wait-list This crate provides WaitList, the most fundamental type for async synchronization. WaitList is implemented as an intrusive linked list of fu

A low-ish level tool for easily writing and hosting WASM based plugins.

A low-ish level tool for easily writing and hosting WASM based plugins. The goal of wasm_plugin is to make communicating across the host-plugin bounda

A low-level I/O ownership and borrowing library

This library introduces OwnedFd, BorrowedFd, and supporting types and traits, and corresponding features for Windows, which implement safe owning and

A Rust framework to develop and use plugins within your project, without worrying about the low-level details.

VPlugin: A plugin framework for Rust. Website | Issues | Documentation VPlugin is a Rust framework to develop and use plugins on applications and libr

A Rust crate that provides a simple interface for LZMA compression and decompression.

rust-lzma Documentation This crate provides a simple interface to liblzma. LZMA is more commonly known as XZ or 7zip, (as in, files with the .xz or .7

Rust mid-level IR Abstract Interpreter

MIRAI MIRAI is an abstract interpreter for the Rust compiler's mid-level intermediate representation (MIR). It is intended to become a widely used sta

Comments
Owner
Jim Chng
Software Engineer. Ph.D. Python, Rust and Golang.
Jim Chng
Translate C++/Rust type into C type with the same memory layout

clayout, translate C++/Rust type into C type with the same memory layout. Generally, clayout is used together with bpftrace. clayout is developed on d

盏一 11 Nov 17, 2022
Mononym is a library for creating unique type-level names for each value in Rust.

Mononym is a library for creating unique type-level names for each value in Rust.

MaybeVoid 52 Dec 16, 2022
A tuple crate for Rust, which introduces a tuple type represented in recusive form.

tuplez This crate introduces a tuple type represented in recursive form rather than parallel form. Motivation The primitive tuple types are represente

Nihil 6 Feb 29, 2024
A principled BSDF pathtracer with an abstracted backend. Perfect for rendering procedural content.

This is a port of the excellent GLSL_Pathtracer to Rust utilizing an abstracted, trait based backend. Perfect for rendering procedural content. Rust F

Markus Moenig 5 Nov 23, 2022
Rust derive macros for automating the boring stuff.

derived: Macros for automating the boring stuff The derived crate provides macros that can simplify all the boring stuff, like writing constructors fo

Sayan 7 Oct 4, 2021
Helper macros: autoimpl, impl_scope

Impl-tools A set of helper macros Macros Autoimpl #[autoimpl] is a variant of #[derive], supporting: explicit generic parameter bounds ignored fields

null 38 Jan 1, 2023
An experimental transpiler to bring tailwind macros to SWC πŸš€

stailwc (speedy tailwind compiler) This is an experimental SWC transpiler to bring compile time tailwind macros to SWC (and nextjs) a-la twin macro. T

Alexander Lyon 139 Dec 20, 2022
CBOR (binary JSON) for Rust with automatic type based decoding and encoding.

THIS PROJECT IS UNMAINTAINED. USE serde_cbor INSTEAD. This crate provides an implementation of RFC 7049, which specifies Concise Binary Object Represe

Andrew Gallant 121 Dec 27, 2022
Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust

Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust, and with an eye towards serializing runtime errors using serde.

Findora Foundation 1 Feb 12, 2022
Type-check non-existing `Phantom` code for Fun And Profit

Sometimes you may want to write Rust code that ought to be type-checked (e.g., borrow-checked) in the same fashion as real Rust code even though that code is never intended to be run / to affect or even reach code generation.

Daniel Henry-Mantilla 4 Jun 5, 2022