# overloaded_literals   [![Latest Version]][crates.io] [![License]][license path] [![requires]][Rust] [![tests_badge]][tests_url] [Latest Version]: https://img.shields.io/crates/v/overloaded_literals.svg [crates.io]: https://crates.io/crates/overloaded_literals [License]: https://img.shields.io/badge/license-MIT-blue.svg [license path]: https://github.com/qqwy/rust-overloaded_literals/blob/main/LICENSE [requires]: https://img.shields.io/badge/rustc-1.65+-lightgray.svg [Rust]: https://rust-lang.org/ [tests_badge]: https://github.com/Qqwy/rust-overloaded_literals/actions/workflows/tests.yml/badge.svg [tests_url]: https://github.com/Qqwy/rust-overloaded_literals/actions/workflows/tests.yml Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation. # Features - Compile-time validation of literals (with decent compiler errors) - Supports `bool`, signed and unsigned integers, floats and `&'static str`. - Construct your types without ceremony or boilerplate. - 100% `no_std` compatible. - Runs on stable rust. MSRV: 1.65.0 Ships with implementations for `std`'s various [NonZero and Wrapping](https://doc.rust-lang.org/stable/std/num/index.html) structs and [CStr](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html). # Usage Add the [overloaded_literals](https://docs.rs/overloaded_literals/latest/overloaded_literals/macro.overloaded_literals.html) attribute to a function. This will rewrite any literals to calls to a trait with the literal as generic const parameter. Because a trait is used, construction of any desired target type which implements the type happens automatically: ```rust use std::num::NonZeroI8; use overloaded_literals::overloaded_literals; #[overloaded_literals] fn example() { let three: NonZeroI8 = 3; let result = three.saturating_mul(2); // <- This '2' also turns into a `NonZero` automatically because of the signature of `saturating_mul`. let six = 6; // <- And this '6' as well assert_eq!(result, six); } example() ``` Trait implementations can perform compile-time validation (using 'const evaluation') on the passed literal. This means that invalid literals are rejected at compile-time with a descriptive error message: ```rust compile_fail use std::num::NonZeroI8; use overloaded_literals::overloaded_literals; #[overloaded_literals] fn mistake() -> NonZeroI8 { let oops: NonZeroI8 = 0; // <- compile error 'NonZero integer literal was 0'. oops.saturating_mul(2) } mistake(); ``` # Implementing the traits As an example, here are the trait implementations for a type `EvenI32` which ensures that the value it stores is even, similarly to how [NonZeroI32](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html) ensures that the contained value is non-zero. ```rust use overloaded_literals::{overloaded_literals, FromLiteralUnsigned, FromLiteralSigned}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct EvenI32(i32); impl EvenI32 { fn new(val: i32) -> Option { if val % 2 != 0 { None } else { Some(EvenI32(val)) } } } // Called for 0 and positive literals: impl FromLiteralUnsigned for EvenI32 { const VALID_LITERAL: u128 = { if LIT % 2 != 0 { panic!("Odd EvenI32 integer literal") } else { LIT } }; fn into_self() -> Self { let raw = >::VALID_LITERAL as i32; EvenI32(raw) } } // Called for negative literals: impl FromLiteralSigned for EvenI32 { const VALID_LITERAL: i128 = { if LIT % 2 != 0 { panic!("Odd EvenI32 integer literal") } else { LIT } }; fn into_self() -> Self { let raw = >::VALID_LITERAL as i32; EvenI32(raw) } } #[overloaded_literals] fn example() { let x: EvenI32 = 100; // let y: EvenI32 = 7; // <- This would cause a compile error :-) } example() ``` Another full example, on how to accept a `str` literal for your datatype, can be found in the documentation of [FromLiteralStr](https://docs.rs/overloaded_literals/latest/overloaded_literals/trait.FromLiteralStr.html). # Missing features The following features are currently missing and would be straightforward additions to later versions of the library: - Support for `char` literals - Support for raw byte str literals (_Requires a similar abstraction as [TypeStr](https://docs.rs/overloaded_literals/latest/overloaded_literals/type_str/trait.TypeStr.html)._)