Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lysender/ea0ab4aa183e4f0a9ed6b209e5a7d36d to your computer and use it in GitHub Desktop.
Save lysender/ea0ab4aa183e4f0a9ed6b209e5a7d36d to your computer and use it in GitHub Desktop.
TIL - Rust enums for some union or generic type scenarios

Coming from TypeScript background, it is common to use either a union type or a generic hints on function parameters.

For rust though, at some point, you need to specify the type.

I have these structs (oversimplified):

#[derive(Serialize, Deserialize)]
struct PublishedJob {
    id: String,
    job: String,
    data: String,
}

#[derive(Serialize, Deserialize)]
struct PublishedEvent {
    id: String,
    event: String,
    data: String,
}

I have a function that should accept either a job or an event. In TypeScript, it may look like this:

// When using generics
function publish(message: T) {
  // do stuff
}

// When using union types
function publish(message: PublishedJob | PublishedEvent) {
  // do stuff
}

I wanted to have the same structure as rust. Using generics don't work since I need to specify the type at some point but the type depends on some runtime data.

Then I realized I could just use enums instead.

#[derive(Serialize, Deserialize)]
enum PublishedPayload {
    Job(PublishedJob),
    Event(PublishedEvent),
}

Then my function signature will look like this:

fn publish(message: PublishedPayload) {
    // do stuff
}

It works and all, however, serde wrapped the object with Job or Event property when serialized. I just want the internal object.

To fix this, we tell serde to use internal tag.

https://serde.rs/enum-representations.html

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum PublishedPayload {
    Job(PublishedJob),
    Event(PublishedEvent),
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment