From 883f1473def2f82b113efba95a795b58f9f6f730 Mon Sep 17 00:00:00 2001 From: Justin Gaffney Date: Tue, 25 Mar 2025 19:52:40 +1000 Subject: [PATCH 1/4] Implement serde::Deserialize for wit-bindgen-rust::Opts --- Cargo.toml | 1 + crates/rust/Cargo.toml | 2 +- crates/rust/src/lib.rs | 14 ++++++++++---- crates/test/Cargo.toml | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67cedcc86..0a2388fd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ anyhow = "1.0.72" bitflags = "2.3.3" heck = { version = "0.5" } pulldown-cmark = { version = "0.9", default-features = false } +serde = { version = "1.0.218", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] } indexmap = "2.0.0" prettyplease = "0.2.20" diff --git a/crates/rust/Cargo.toml b/crates/rust/Cargo.toml index 3a6ea5952..cc33aac87 100644 --- a/crates/rust/Cargo.toml +++ b/crates/rust/Cargo.toml @@ -25,6 +25,7 @@ clap = { workspace = true, optional = true } indexmap = { workspace = true } syn = { workspace = true } prettyplease = { workspace = true } +serde = { workspace = true } [dev-dependencies] futures = { workspace = true } @@ -32,5 +33,4 @@ wit-bindgen = { path = '../guest-rust', features = ['async'] } wit-bindgen-rt = { path = '../guest-rust/rt' } test-helpers = { path = '../test-helpers' } # For use with the custom attributes test -serde = { version = "1.0", features = ["derive"] } serde_json = "1" diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 1f7151b4f..8b4a635c1 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -3,6 +3,7 @@ use anyhow::{bail, Result}; use core::panic; use heck::*; use indexmap::{IndexMap, IndexSet}; +use serde::Deserialize; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::{self, Write as _}; use std::mem; @@ -133,7 +134,8 @@ fn parse_with(s: &str) -> Result<(String, WithOption), String> { Ok((k.to_string(), v)) } -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Deserialize)] +#[serde(rename_all = "kebab-case")] pub enum AsyncConfig { #[default] None, @@ -179,8 +181,9 @@ fn parse_async(s: &str) -> Result { }) } -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Deserialize)] #[cfg_attr(feature = "clap", derive(clap::Parser))] +#[serde(rename_all = "kebab-case")] pub struct Opts { /// Whether or not a formatter is executed to format generated code. #[cfg_attr(feature = "clap", arg(long))] @@ -315,6 +318,7 @@ pub struct Opts { /// - import: or /// - export: #[cfg_attr(feature = "clap", arg(long = "async", value_parser = parse_async, default_value = "none"))] + #[serde(rename = "async")] pub async_: AsyncConfig, } @@ -1444,7 +1448,8 @@ fn group_by_resource<'a>( by_resource } -#[derive(Default, Debug, Clone, Copy)] +#[derive(Default, Debug, Clone, Copy, Deserialize)] +#[serde(rename_all = "kebab-case")] pub enum Ownership { /// Generated types will be composed entirely of owning fields, regardless /// of whether they are used as parameters to imports or not. @@ -1498,7 +1503,8 @@ impl fmt::Display for Ownership { } /// Options for with "with" remappings. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "kebab-case")] pub enum WithOption { Path(String), Generate, diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index 365139e16..afe8034d7 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -21,7 +21,7 @@ heck = { workspace = true } log = "0.4.26" rayon = "1.10.0" regex = "1.11.1" -serde = { version = "1.0.218", features = ["derive"] } +serde = { workspace = true } toml = "0.8.20" wasi-preview1-component-adapter-provider = "30.0.2" wac-parser = "0.6.1" From 2a3400a5bdc1b4c0164332b2e3ce21f9e47f8df3 Mon Sep 17 00:00:00 2001 From: Justin Gaffney Date: Wed, 26 Mar 2025 20:27:08 +1000 Subject: [PATCH 2/4] Change serde to an optional dependency --- crates/rust/Cargo.toml | 2 +- crates/rust/src/lib.rs | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/rust/Cargo.toml b/crates/rust/Cargo.toml index cc33aac87..91cbbe1cc 100644 --- a/crates/rust/Cargo.toml +++ b/crates/rust/Cargo.toml @@ -25,7 +25,7 @@ clap = { workspace = true, optional = true } indexmap = { workspace = true } syn = { workspace = true } prettyplease = { workspace = true } -serde = { workspace = true } +serde = { workspace = true, optional = true } [dev-dependencies] futures = { workspace = true } diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 8b4a635c1..d30147496 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -3,7 +3,6 @@ use anyhow::{bail, Result}; use core::panic; use heck::*; use indexmap::{IndexMap, IndexSet}; -use serde::Deserialize; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::{self, Write as _}; use std::mem; @@ -117,6 +116,8 @@ enum RuntimeItem { } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub enum ExportKey { World, Name(String), @@ -134,8 +135,9 @@ fn parse_with(s: &str) -> Result<(String, WithOption), String> { Ok((k.to_string(), v)) } -#[derive(Default, Debug, Clone, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[derive(Default, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub enum AsyncConfig { #[default] None, @@ -181,9 +183,10 @@ fn parse_async(s: &str) -> Result { }) } -#[derive(Default, Debug, Clone, Deserialize)] +#[derive(Default, Debug, Clone)] #[cfg_attr(feature = "clap", derive(clap::Parser))] -#[serde(rename_all = "kebab-case")] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub struct Opts { /// Whether or not a formatter is executed to format generated code. #[cfg_attr(feature = "clap", arg(long))] @@ -318,7 +321,7 @@ pub struct Opts { /// - import: or /// - export: #[cfg_attr(feature = "clap", arg(long = "async", value_parser = parse_async, default_value = "none"))] - #[serde(rename = "async")] + #[cfg_attr(feature = "serde", serde(rename = "async"))] pub async_: AsyncConfig, } @@ -1448,8 +1451,9 @@ fn group_by_resource<'a>( by_resource } -#[derive(Default, Debug, Clone, Copy, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[derive(Default, Debug, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub enum Ownership { /// Generated types will be composed entirely of owning fields, regardless /// of whether they are used as parameters to imports or not. @@ -1503,8 +1507,9 @@ impl fmt::Display for Ownership { } /// Options for with "with" remappings. -#[derive(Debug, Clone, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub enum WithOption { Path(String), Generate, From 0e712a2f29db196c99c3ed6d18f91ed0a094edd6 Mon Sep 17 00:00:00 2001 From: Justin Gaffney Date: Wed, 26 Mar 2025 20:50:09 +1000 Subject: [PATCH 3/4] Combine serde feature attributes into a single cfg_attr line --- crates/rust/src/lib.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index d30147496..96163da78 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -116,8 +116,7 @@ enum RuntimeItem { } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] pub enum ExportKey { World, Name(String), @@ -136,8 +135,7 @@ fn parse_with(s: &str) -> Result<(String, WithOption), String> { } #[derive(Default, Debug, Clone)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] pub enum AsyncConfig { #[default] None, @@ -185,8 +183,7 @@ fn parse_async(s: &str) -> Result { #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "clap", derive(clap::Parser))] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] pub struct Opts { /// Whether or not a formatter is executed to format generated code. #[cfg_attr(feature = "clap", arg(long))] @@ -1452,8 +1449,7 @@ fn group_by_resource<'a>( } #[derive(Default, Debug, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] pub enum Ownership { /// Generated types will be composed entirely of owning fields, regardless /// of whether they are used as parameters to imports or not. @@ -1508,8 +1504,7 @@ impl fmt::Display for Ownership { /// Options for with "with" remappings. #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] pub enum WithOption { Path(String), Generate, From 8e1e2106f6fb8e062864abc5a111acb82671f128 Mon Sep 17 00:00:00 2001 From: Justin Gaffney Date: Wed, 26 Mar 2025 20:51:25 +1000 Subject: [PATCH 4/4] Run `cargo fmt` --- crates/rust/src/lib.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 96163da78..15f5f701b 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -116,7 +116,11 @@ enum RuntimeItem { } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize), + serde(rename_all = "kebab-case") +)] pub enum ExportKey { World, Name(String), @@ -135,7 +139,11 @@ fn parse_with(s: &str) -> Result<(String, WithOption), String> { } #[derive(Default, Debug, Clone)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize), + serde(rename_all = "kebab-case") +)] pub enum AsyncConfig { #[default] None, @@ -183,7 +191,11 @@ fn parse_async(s: &str) -> Result { #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "clap", derive(clap::Parser))] -#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize), + serde(rename_all = "kebab-case") +)] pub struct Opts { /// Whether or not a formatter is executed to format generated code. #[cfg_attr(feature = "clap", arg(long))] @@ -1449,7 +1461,11 @@ fn group_by_resource<'a>( } #[derive(Default, Debug, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize), + serde(rename_all = "kebab-case") +)] pub enum Ownership { /// Generated types will be composed entirely of owning fields, regardless /// of whether they are used as parameters to imports or not. @@ -1504,7 +1520,11 @@ impl fmt::Display for Ownership { /// Options for with "with" remappings. #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "kebab-case"))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize), + serde(rename_all = "kebab-case") +)] pub enum WithOption { Path(String), Generate,