[][src]Crate fluent_impl

A procedural macro that generates chaining methods from non-chaining ones in an impl block.

When applied to an impl block, #[fluent_impl] will scan all methods in the block in search for chain-able methods, and generate chaining methods from them.

Chain-able methods are the ones with &mut self as a first argument, and return nothing. That's it, there are no other restrictions.

Usage

Add fluent-impl to the dependencies in Cargo.toml:

[dependencies]
fluent-impl = "0.1"

Then add the following to the top of src/lib.rs:

This example is not tested
// Will be stabilized soon
#![feature(use_extern_macros)]

extern crate fluent_impl;

use fluent_impl::{fluent_impl, fluent_impl_opts};

Examples

If we have a simple struct with a simple impl block:

#[derive(Default, PartialEq, Debug)]
pub struct Simple {
    num: i32,
}

impl Simple {
    // ...
    pub fn add_1(&mut self) {
        self.num +=1;
    }
}

Then we add the macro attribute to the impl block:

This example is not tested
#[fluent_impl]
impl Simple {
    // ...
    pub fn add_1(&mut self) {
        self.num +=1;
    }
}

The macro will generate a new impl block with the content:

This example is not tested
#[doc = "Chaining (fluent) methods for [`Simple`]."]
impl Simple {
    #[doc = "The chaining (fluent) equivalent of [`add_1()`].\n\n [`add_1`]: Simple::add_1\n [`add_1()`]: Simple::add_1"]
    pub fn with_add_1(mut self) -> Self {
        self.add_1();
        self
    }
}

A full more involved example can be found bellow the Attribute Configuration section.

Attribute Configuration

#[fluent_impl] is configurable with comma-separated options passed to the attribute itself, and options passed to a method-level attribute #[fluent_impl_opts].

#[fluent_impl] Attribute Options

(inblock, non_public, prefix, impl_doc, doc)

impl block-level configuration.

Example

This example is not tested
#[fluent_impl(inblock, non_public, prefix="chain_")]
impl Simple {
    // ...
}

Options

#[fluent_impl_opts] Attribute Options

(inblock, non_public, skip, prefix, rename, name, doc)

Options passed to override block-level defaults, or set method-specific configurations.

Unlike #[fluent_impl], this attribute:

  1. Applies to methods instead of impl blocks.
  2. Can be passed multiple times to the same method if you please.

Example

This example is not tested
#[fluent_impl]
impl Simple {
    #[fluent_impl_opts(non_public, inblock)]
    #[fluent_impl_opts(prefix="chain_", rename="added_1")]
    fn add_1(&mut self) {
        // ...
    }
}

Options

Inherited

Method Specific

Full Example

#![feature(use_extern_macros)]

extern crate fluent_impl;

pub mod m {
    use fluent_impl::{fluent_impl, fluent_impl_opts};
    use std::borrow::Borrow;
    use std::ops::AddAssign;

    #[derive(PartialEq, Debug)]
    pub struct TCounter(pub u32);

    #[derive(PartialEq, Debug)]
    pub struct St<A: AddAssign> {
        value: A,
        text: String,
    }

    #[fluent_impl]
    // impl block with generic arguments works
    impl<A: AddAssign> St<A> {
        // Constants (or any other items) in impl block are okay
        pub(crate) const C_TC: u32 = 100;

        pub fn new(value: A, text: String) -> Self {
            Self { value, text }
        }

        pub fn get_value(&self) -> &A {
            &self.value
        }

        pub fn get_text(&self) -> &str {
            &self.text
        }

        #[fluent_impl_opts(rename = "added_value")]
        // Destructuring patterns in method arguments are okay
        pub fn add_value(
            &mut self,
            to_be_added: A,
            TCounter(counter): &mut TCounter,
        ) {
            self.value += to_be_added;
            *counter += 1;
        }

        #[fluent_impl_opts(rename = "appended_text")]
        // Generic method arguments are okay
        pub fn append_text<S: Borrow<str>>(&mut self, arg: S) {
            self.text += arg.borrow();
        }

        #[fluent_impl_opts(rename = "appended_text_impl_trait")]
        // Needless to say, impl Trait method arguments are also okay
        pub fn append_text_impl_trait(&mut self, arg: impl Borrow<str>) {
            self.text += arg.borrow();
        }
    }
}

fn main() {
    use m::{St, TCounter};
    // ========
    let mut tc1 = TCounter(St::<u32>::C_TC);
    let mut s1 = St::new(0u32, "".into());
    s1.append_text("simple ");
    s1.append_text::<&str>("turbo fish ");
    s1.append_text_impl_trait("impl trait");
    s1.add_value(5, &mut tc1);
    assert_eq!(s1.get_text(), "simple turbo fish impl trait");
    assert_eq!(tc1, TCounter(St::<u32>::C_TC + 1));
    // ========
    let mut tc2 = TCounter(St::<u32>::C_TC);
    let s2 = St::new(0u32, "".into())
        .with_appended_text("simple ")
        .with_appended_text::<&str>("turbo fish ")
        .with_appended_text_impl_trait("impl trait")
        .with_added_value(5, &mut tc2);
    assert_eq!(s2, s1);
    assert_eq!(tc2, tc1);
}

Functions

fluent_impl

Check the top-level documentation of this crate

fluent_impl_opts

Check the top-level documentation of this crate