Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stackable-versioned): Generate From implementations for automatic versions upgrades #790

Merged
merged 19 commits into from
Jun 5, 2024

Conversation

Techassi
Copy link
Member

@Techassi Techassi commented May 21, 2024

Description

Tracked by stackabletech/issues#507, follow-up of #764, blocked by #793

This PR adds code generation for From<OLD> for NEW implementations to enable conversion between versions. The macro also allows to implement the From trait by hand if customization is required.

Additionally, it adds support to customize the default function (used in the automatically generated From impl) for added fields.

Examples

Generated From implementations

#[versioned(
    version(name = "v1alpha1"),
    version(name = "v1beta1"),
    version(name = "v1")
)]
pub struct Foo {
    #[versioned(
        added(since = "v1beta1"),
        deprecated(since = "v1", note = "not needed")
    )]
    deprecated_bar: usize,
    baz: bool,
}

// Produces ...

#[automatically_derived]
pub mod v1alpha1 {
    pub struct Foo {
        pub baz: bool,
    }
}
#[automatically_derived]
#[allow(deprecated)]
impl From<v1alpha1::Foo> for v1beta1::Foo {
    fn from(__sv_foo: v1alpha1::Foo) -> Self {
        Self {
            bar: std::default::Default::default(),
            baz: __sv_foo.baz,
        }
    }
}
#[automatically_derived]
pub mod v1beta1 {
    pub struct Foo {
        pub bar: usize,
        pub baz: bool,
    }
}
#[automatically_derived]
#[allow(deprecated)]
impl From<v1beta1::Foo> for v1::Foo {
    fn from(__sv_foo: v1beta1::Foo) -> Self {
        Self {
            deprecated_bar: __sv_foo.bar,
            baz: __sv_foo.baz,
        }
    }
}
#[automatically_derived]
pub mod v1 {
    pub struct Foo {
        #[deprecated = "not needed"]
        pub deprecated_bar: usize,
        pub baz: bool,
    }
}

// Which can be used like this ...

let foo_v1alpha1 = v1alpha1::Foo { baz: true };
let foo_v1beta1 = v1beta1::Foo::from(foo_v1alpha1);
let foo_v1 = v1::Foo::from(foo_v1beta1);

assert_eq!(foo_v1.deprecated_bar, 0);
assert!(foo_v1.baz);

Skip generating From implementations

The generation can be skipped at the container level (no implementations are generated) or at the version level (only the generation from that to the next version is skipped).

#[versioned(
    version(name = "v1alpha1"),
    version(name = "v1beta1"),
    version(name = "v1"),
    options(skip(from))
)]
pub struct Foo {
    #[versioned(
        added(since = "v1beta1"),
        deprecated(since = "v1", note = "not needed")
    )]
    deprecated_bar: usize,
    baz: bool,
}

// Or ...

#[versioned(
    version(name = "v1alpha1"),
    version(name = "v1beta1", skip(from)),
    version(name = "v1")
)]
pub struct Foo {
    #[versioned(
        added(since = "v1beta1"),
        deprecated(since = "v1", note = "not needed")
    )]
    deprecated_bar: usize,
    baz: bool,
}

Custom default function for added fields

#[versioned(
    version(name = "v1alpha1"),
    version(name = "v1beta1"),
    version(name = "v1")
)]
pub struct Foo {
    #[versioned(
        added(since = "v1beta1", default = "default_bar"),
        deprecated(since = "v1", note = "not needed")
    )]
    deprecated_bar: usize,
    baz: bool,
}

// Can be used like this ...

fn default_bar() -> usize {
    42
}

let foo_v1alpha1 = v1alpha1::Foo { baz: true };
let foo_v1beta1 = v1beta1::Foo::from(foo_v1alpha1);

assert_eq!(foo_v1beta1.bar, 42);
assert!(foo_v1beta1.baz);

Reviewer

Preview Give feedback

@Techassi Techassi force-pushed the feat/crd-versioning-from-impls branch from 044b659 to 7e16ec4 Compare May 23, 2024 14:58
Techassi and others added 10 commits May 28, 2024 10:16
This commit separate the code into two crates: the
core stackable-versioned crate, which provides a
few utility traits and types and also re-exports
the macros from the stackable-versioned-macros
crate. This is because, crates (or libraries)
marked as proc-macro libraries don't support
export anything other than macro items.

It also re-adds the basic From impl which was hard
to keep across the previous merge conflict. This
basic impl will currently panic, as the inner
function is not yet implemented. This will follow.

It additionally separates the generation code into
multiple functions to more easily generate the
different parts of code, like modules, struct
fields and From impls.
There is at least one known rough edge: The #[allow(deprecated)]
attribute is always included in the generated output, regardless
if the individual From implementation actually needs it. The
attribute is only required when the next version of the struct
includes a field which is marked as deprecated.
Can be skipped both on the container level (no impls are generated)
or at the version level (no impls are generated for that version).
@Techassi Techassi changed the title feat(stackable-versioned): Generate From implementations for automatic conversion between versions feat(stackable-versioned): Generate From implementations for automatic versions upgrades Jun 5, 2024
@Techassi Techassi marked this pull request as ready for review June 5, 2024 11:05
@Techassi Techassi requested a review from NickLarsenNZ June 5, 2024 11:05
crates/stackable-versioned-macros/src/lib.rs Outdated Show resolved Hide resolved
crates/stackable-versioned-macros/src/lib.rs Outdated Show resolved Hide resolved
@NickLarsenNZ NickLarsenNZ self-requested a review June 5, 2024 12:13
Copy link
Member

@NickLarsenNZ NickLarsenNZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Techassi Techassi added this pull request to the merge queue Jun 5, 2024
Merged via the queue into main with commit 1c2d22c Jun 5, 2024
17 checks passed
@Techassi Techassi deleted the feat/crd-versioning-from-impls branch June 5, 2024 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants