Skip to content

Macro to add common fields to an enum #436

@rklaehn

Description

@rklaehn

I got a case where I have a large enum with common fields. I wrote a macro to add the common fields, so the code can be DRYed and look nicer.

Would this be a good addition to strum?

Below is a use case from our code base in https://github.com/n0-computer/iroh

With macro:

/// Connection errors
#[common_fields({
    backtrace: Option<Backtrace>,
    #[snafu(implicit)]
    span_trace: n0_snafu::SpanTrace,
})]
#[allow(missing_docs)]
#[derive(Debug, Snafu)]
#[non_exhaustive]
#[snafu(visibility(pub(crate)))]
pub enum ConnectError {
    #[snafu(display("Invalid URL for websocket: {url}"))]
    InvalidWebsocketUrl { url: Url },
    #[snafu(display("Invalid relay URL: {url}"))]
    InvalidRelayUrl { url: Url },
    #[snafu(transparent)]
    Websocket { source: tokio_websockets::Error },
    #[snafu(transparent)]
    Handshake { source: HandshakeError },
    #[snafu(transparent)]
    Dial { source: DialError },
    #[snafu(display("Unexpected status during upgrade: {code}"))]
    UnexpectedUpgradeStatus { code: hyper::StatusCode },
    #[snafu(display("Failed to upgrade response"))]
    Upgrade { source: hyper::Error },
    #[snafu(display("Invalid TLS servername"))]
    InvalidTlsServername {},
    #[snafu(display("No local address available"))]
    NoLocalAddr {},
    #[snafu(display("tls connection failed"))]
    Tls { source: std::io::Error },
    #[cfg(wasm_browser)]
    #[snafu(display("The relay protocol is not available in browsers"))]
    RelayProtoNotAvailable {},
}

Without macro:

/// Connection errors
#[allow(missing_docs)]
#[derive(Debug, Snafu)]
#[non_exhaustive]
#[snafu(visibility(pub(crate)))]
pub enum ConnectError {
    #[snafu(display("Invalid URL for websocket: {url}"))]
    InvalidWebsocketUrl {
        url: Url,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("Invalid relay URL: {url}"))]
    InvalidRelayUrl {
        url: Url,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(transparent)]
    Websocket {
        source: tokio_websockets::Error,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(transparent)]
    Handshake {
        source: HandshakeError,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(transparent)]
    Dial {
        source: DialError,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("Unexpected status during upgrade: {code}"))]
    UnexpectedUpgradeStatus {
        code: hyper::StatusCode,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("Failed to upgrade response"))]
    Upgrade {
        source: hyper::Error,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("Invalid TLS servername"))]
    InvalidTlsServername {
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("No local address available"))]
    NoLocalAddr {
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[snafu(display("tls connection failed"))]
    Tls {
        source: std::io::Error,
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
    #[cfg(wasm_browser)]
    #[snafu(display("The relay protocol is not available in browsers"))]
    RelayProtoNotAvailable {
        backtrace: Option<Backtrace>,
        #[snafu(implicit)]
        span_trace: n0_snafu::SpanTrace,
    },
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions