Giter Club home page Giter Club logo

spread_macros's Introduction

spread_macros crate spread_macros documentation

Macros around an extended spread syntax.

spread!

An extension of the spread/struct update syntax that allow taking fields from different type structs, as long as the listed fields have the same type in both structs. It supports modifier prefixes allowing to perform common transformations, such as cloning, converting, taking a reference; or even custom transformation by providing a function path.

use spread_macros::spread;

struct Foo {
    one: String,
    two: u32,
    three: u32,
    four: &'static str,
}

struct Bar<'a> {
    one: String,
    two: u64,
    three: &'a u32,
    four: String,
}

let foo = Foo {
    one: "Hello".to_string(),
    two: 2,
    three: 3,
    four: "HELLO",
};

let two = 2u32;
let bar = spread!(Bar {
    >two, // calls .into()
    {
        +one, // calls .clone()
        &three, // takes a reference
        [str::to_lowercase] four,
    } in &foo,
});

anon!

Generate a value of an anonymous struct with provided fields whose types are inferred. Can be used to bundle many variables in a single struct to then be used in spread!. It supports the same features as spread! (lists and modifiers) except for the final struct update syntax.

use spread_macros::anon;

struct Foo {
    one: String,
    two: u32,
    three: u32,
}

let foo = Foo {
    one: "Hello".to_string(),
    two: 2,
    three: 3,
};
let four = 4u32;

// Creates an anonymous struct with the given fields.
let exemple = anon! {
    { +one, >two, &three } in &foo,
    four,
};

// When using `>` (into) the field must be used for its type to be inferred.
let inferred: u64 = exemple.two;
println!("{exemple:?})");

slet!

Avoids having to write a lot of transforations like let variable_with_long_name = variable_with_long_name.clone() (which is common with closures and async blocks) by listing all the identifiers and transformations with the same syntax as anon!. In additation, each field name can be prefixed by mut (before a potential modifier) to make a let mut binding.

use spread_macros::slet;

let foo = "Hello".to_string();
let bar = 42u32;

slet! {mut +foo, >bar};
let inferred: u64 = bar;

fn_struct!

Generates a struct representing the arguments of a given function or method, allowing to use Rust's struct update syntax, spread! and Default with function arguments. The fields listed can use modifiers from spread! like &, which allows for exemple to call functions with reference arguments using a struct without references, which can thus implement Default. The struct can be generic over the types of the function arguments, while the call function can also be generic over types not appearing in the arguments.

It is targeted to be used when writing tests in which a function with many parameters is called often and for which repeated arguments can be applied using spread!.

Asserts that some fields of the provided value match the expectation.

use spread_macros::fn_struct;

fn foo(foo: u32, bar: u32, baz: &u32) -> u32 {
    foo + bar + baz
}

fn_struct!(
    struct Foo
    for fn foo(
        one: u32 = 1,
        >two: u16 = 2, // converts from struct's u16 to functions u32
        &three: u32 = 3 // struct stores value, function takes reference
    ) -> u32
);

let res = Foo {
    three: 33,
    ..Default::default()
}
.call();

assert_eq!(res, 1 + 2 + 33);

assert_fields_eq!

This expectation can be expressed in 2 ways:

  • Another value can be provided, followed by a list of fields both values have in common and should be equal.
  • An anonymous struct with the same syntax as anon!.

Afterward, the macro accepts a custom panic message with formating like assert_eq!.

It uses the in-scope assert_eq! macro, which allows to use alternative macros like similar_asserts::assert_eq! if wanted.

use spread_macros::{anon, assert_fields_eq};

#[derive(Clone, Debug)]
struct Exemple {
    _foo: u32,
    bar: String,
    baz: bool,
}

let exemple = Exemple {
    _foo: 42,
    bar: String::from("exemple"),
    baz: true,
};

let expected = anon! {
    bar: String::from("exemple"),
    baz: true,
    other: "other",
};

assert_fields_eq!(exemple, {
    bar: String::from("exemple"),
    { +baz } in &expected,
});

assert_fields_eq!(
    exemple,
    expected,
    [bar, baz],
    "unexpected fields in {exemple:?}"
);

spread_macros's People

Contributors

nanocryk avatar

Stargazers

 avatar

Watchers

 avatar

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.