Derive macro implementing 'From' for structs

Overview

derive-from-ext

A derive macro that auto implements 'std::convert::From' for structs. The default behaviour is to create an instance of the structure by calling .into() on each of the source structure properties. The source struct properties can be mapped using different names and methods by using field attributes to override the default behaviour.

Installing

Include in your Cargo.toml file:

[dependencies]
derive-from-ext = "0.2"

Examples

use derive_from_ext::From;

struct A {
    prop1: String,
}

#[derive(From, Debug)]
#[from(A)]
struct B {
    prop1: String,
}

let a = A { prop1: "Test".to_string() };
let b: B = a.into();
dbg!(b); //automatically converted into type B and can use implementations on this type

Defaults

If a source structure has few properties than the current structure then the property can be skipped by tagging with 'skip':

#[from(A)]
struct B [
    #[from(skip)]
    other_prop: String,
]

Note: this only works where a default can be assigned to the property value and is equivalent to setting the skip method to 'std::default::Default::default' as below.

#[from(A)]
struct B [
    #[from(skip, default="String::from(\"New value\")")]
    other_prop: String,
]

Alternative method

To use an alternative method to create the value for the structure property, a property attribute can be used with the path of the met:

fn lowercase(str: String) -> String {
    str.to_lowercase()
}

#[from(A)]
struct B {
    #[from(map="lowercase")]
    other_prop: String,
}

Different property names

To map from a different property on the source structure, a property attribute can be used:

#[from(A)]
struct B {
    #[from(rename="prop1")]
    other_prop: String,
}

Multiple structs

To support multiple source structures, the 'from' attribute can be extended to include the other structures. The attributes can then also override source-specific options for each source structure:

#[from(A, B)]
struct C {
    #[from(overrides=( A=(skip=true), B=(map="lowercase") ))]
    other_prop: String,
}

Alternatives

If you do not require the features above and only want to convert a struct into matching struct you may be better off using derive_more instead.

You might also like...
hado-rshado — A little macro for writing haskell-like do expressions without too much ceremony

hado Monadic haskell-like expressions brought to rust via the hado! macro What? A little macro for writing haskell-like do expressions without too muc

A Rust macro for writing regex pattern matching.

regexm A Rust macro for writing regex pattern matching.

Rust crate that provides a convenient macro to quickly plot variables.
Rust crate that provides a convenient macro to quickly plot variables.

Debug Plotter This crate provides a convenient macro to quickly plot variables. Documentation For more information on how to use this crate, please ta

A proc-macro to get Vecu8 from struct and vise versa

byteme A proc-macro to convert a struct into Vec and back by implemeting From trait on the struct. The conversion is Big Endian by default. We have ma

Rust macro to make recursive function run on the heap (i.e. no stack overflow).

Decurse Example #[decurse::decurse] // 👈 Slap this on your recursive function and stop worrying about stack overflow! fn factorial(x: u32) - u32 {

Rust macro that uses GPT3 codex to generate code at compiletime

gpt3_macro Rust macro that uses GPT3 codex to generate code at compiletime. Just describe what you want the function to do and (optionally) define a f

No-nonsense input!(...) macro for Rust

No-nonsense input!(...) macro for Rust

A proc macro for creating compile-time checked CSS class sets, in the style of classNames

semester Semester is a declarative CSS conditional class name joiner, in the style of React's classnames. It's intended for use in web frameworks (lik

Proc. macro to generate C-like `enum` tags.

Continuous Integration Documentation Crates.io #[derive(EnumTag)] This crate provides a proc. macro to derive the EnumTag trait for the given Rust enu

Comments
  • filter arguments passed to From derive

    filter arguments passed to From derive

    Hi! Thanks for this crate, I spend so many time looking for something looking for a solution to map my databases structs to protobuf generated structs without doing everything by hand. When using it I found two-three cases when other attributes make that From derive panic because it doesn't filter arguments passed to it and my struct looks quite encased in derives and extra arguments, here a small example:

    use crate::db::users::LocalStorage as DBLocalStorage;
    #[derive(derive_from_ext::From)]
    #[from(DBLocalStorage)]
    #[derive(serde::Deserialize, serde::Serialize)]
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct LocalStorage {
        #[prost(int32, required, tag="1")]
        pub id: i32,
        #[prost(string, required, tag="2")]
        pub name: ::prost::alloc::string::String,
        #[prost(string, optional, tag="3")]
        pub value: ::core::option::Option<::prost::alloc::string::String>,
    }
    

    With those small fixes it now works. BTW. do you think it could work also with full struct patches? Example what I mean

    #[derive(derive_from_ext::From)]
    #[from(crate::db::users::LocalStorage)]
    #[derive(serde::Deserialize, serde::Serialize)]
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct LocalStorage {
        #[prost(int32, required, tag="1")]
        pub id: i32,
        #[prost(string, required, tag="2")]
        pub name: ::prost::alloc::string::String,
        #[prost(string, optional, tag="3")]
        pub value: ::core::option::Option<::prost::alloc::string::String>,
    }
    

    I tried doing that myself but that looks like a bigger rewrite and I am really new to writing dervies macros.

    opened by dragonnn 3
Owner
Andrew Lowndes
Rust / Typescript, user interfaces, security, computer graphics.
Andrew Lowndes
Derive macro for encoding/decoding instructions and operands as bytecode

bytecoding Derive macro for encoding and decoding instructions and operands as bytecode. Documentation License Licensed under either of Apache License

Niklas Sauter 15 Mar 20, 2022
This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to the arrow format.

Arrow2-derive - derive for Arrow2 This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to th

Jorge Leitao 29 Dec 27, 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
Derive with constructor for each field in struct.

A custom derive implementation for #[derive(with)] Get started 1.Generate with constructor for each field use derive_with::with; #[derive(with, Defau

SystemX Labs 4 Oct 22, 2023
Minimal, flexible framework for implementing solutions to Advent of Code in Rust

This is advent_of_code_traits, a minimal, flexible framework for implementing solutions to Advent of Code in Rust.

David 8 Apr 17, 2022
A framework for iterating over collections of types implementing a trait without virtual dispatch

zero_v Zero_V is an experiment in defining behavior over collections of objects implementing some trait without dynamic polymorphism.

null 13 Jul 28, 2022
An unofficial and incomplete no_std Rust library for implementing the ElectricUI Binary Protocol

An unofficial and incomplete no_std Rust library for implementing the ElectricUI Binary Protocol

Jon 2 Mar 29, 2022
An ActivityPub home server written in Rust, implementing the Mastodon API.

Tafarn An ActivityPub home server written in Rust, implementing the Mastodon API. At present no web UI is provided, the API is the only way to interac

✨ Q (it/its) ✨ 12 Jan 22, 2023
A xdg-desktop-portal for wlroots based compositors implementing zwlr_screencopy

xdg-desktop-portal-luminous An alternative to xdg-desktop-portal-wlr for wlroots compositors. This project is a stand alone binary and does not depend

Waycrate 7 Aug 27, 2023
Macro for Python-esque comprehensions in Rust

Cute Macro for Python-esque list comprehensions in Rust. The c! macro implements list and hashmap comprehensions similar to those found in Python, all

Matt Gathu 306 Jan 6, 2023