GithubHelp home page GithubHelp logo

qqwy / rust-overloaded_literals Goto Github PK

View Code? Open in Web Editor NEW
8.0 2.0 1.0 75 KB

Rust crate: Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation.

Home Page: https://crates.io/crates/overloaded_literals

Rust 100.00%
generics literals macros rust syntactic-sugar

rust-overloaded_literals's Introduction

overloaded_literals โ€ƒ Latest Version License requires tests_badge

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 structs and CStr.

Usage

Add the overloaded_literals 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:

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:

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 ensures that the contained value is non-zero.

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<Self> {
        if val % 2 != 0 {
            None
        } else {
            Some(EvenI32(val))
        }
    }
}

// Called for 0 and positive literals:
impl<const LIT: u128> FromLiteralUnsigned<LIT> for EvenI32 {
    const VALID_LITERAL: u128 = {
        if LIT % 2 != 0 {
            panic!("Odd EvenI32 integer literal")
        } else {
            LIT
        }
    };
    fn into_self() -> Self {
        let raw = <Self as FromLiteralUnsigned<LIT>>::VALID_LITERAL as i32;
        EvenI32(raw)
    }
}

// Called for negative literals:
impl<const LIT: i128> FromLiteralSigned<LIT> for EvenI32 {
    const VALID_LITERAL: i128 = {
        if LIT % 2 != 0 {
            panic!("Odd EvenI32 integer literal")
        } else {
            LIT
        }
    };
    fn into_self() -> Self {
        let raw = <Self as FromLiteralSigned<LIT>>::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.

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.)

rust-overloaded_literals's People

Contributors

qqwy avatar vortexofdoom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

vortexofdoom

rust-overloaded_literals's Issues

Soundness issue: writing to `addr_of!(arr)` is UB

I stumbled upon the following code in this crate:

let mut arr: [u8; MAX_STR_LIT_LEN] = [0; MAX_STR_LIT_LEN];
let target_ptr = unsafe { core::mem::transmute(core::ptr::addr_of!(arr) as *const u8) }; // <- Poor man's addr_of_mut!
unsafe { core::ptr::copy_nonoverlapping(first_elem_ptr, target_ptr, 1) };
unsafe { core::ptr::copy_nonoverlapping(rest_ptr, target_ptr.add(1), Rest::LEN) };
arr

That code is UB. addr_of!(arr) creates a read-only pointer and then later there is a write happening. That UB will likely in the future be detected by rustc so this code will then be rejected. (See here for our policy around UB in const.)

There is currently no way to actually use copy_nonoverlapping in a const; that function got stabilized accidentally (and we are debating whether to revert that stabilization, since it encourages misuse, such as what we are seeing in this crate).

As an alternative for this crate, you could use a loop that repeats arr[i] = ...; you don't actually need copy_nonoverlapping here I think.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.