How can I implement a trait in scope for an enum of existing types for which the trait is implemented?

人走茶凉 提交于 2021-01-29 11:10:03

问题


How can I implement a trait in scope for an enum of existing types for which the trait is implemented?

I have this:

extern crate pnet;

use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::ipv6::Ipv6Packet;

enum EthernetType {
    IPv4,
    ARP,
    VLAN,
    IPv6,
    Unknown(u16),
}

enum IPPacket<'a> {
    IPv4(Ipv4Packet<'a>),
    IPv6(Ipv6Packet<'a>),
}

fn ip_decode(pkt: &[u8]) -> IPPacket {
    let version = (pkt[0] & 0xf0) >> 4;
    if version == 4 {
        IPPacket::IPv4(Ipv4Packet::new(&pkt).unwrap())
    } else {
        IPPacket::IPv6(Ipv6Packet::new(&pkt).unwrap())
    }
}

fn main() {
    // Parse ethernet packet here...
    // ...
    let ip_packet = ip_decode(b"deadbeef");
    println!("{:?}", ip_packet.payload());
}

The compiler complains that I have not implemented the Packet trait for my enum:

error[E0599]: no method named `payload` found for type `IPPacket<'_>` in the current scope
  --> src/main.rs:32:32
   |
14 | enum IPPacket<'a> {
   | ----------------- method `payload` not found for this
...
32 |     println!("{:?}", ip_packet.payload());
   |                                ^^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `payload`, perhaps you need to implement it:
           candidate #1: `pnet::packet::Packet`

I thought that the Packet trait would be derived through Ipv4Packet<'a> and Ipv6Packet<'a>?


回答1:


How can I implement a trait in scope for an enum of existing types

You implement a trait for an enum the same way you implement a trait for a struct:

trait Noise {
    fn noise(&self);
}

enum Foo {
    Bar,
    Baz,
}

impl Noise for Foo {
    fn noise(&self) {
        match self {
            Foo::Bar => println!("bar bar bar"),
            Foo::Baz => println!("baz baz baz"),
        }
    }
}

an enum of existing types for which the trait is implemented

I thought that the Packet trait would be derived

It is not. Doing so would prevent people from implementing their own code for the trait if they needed. It also wouldn't work in all cases, such as when one variant didn't implement it.

trait Noise {
    fn noise(&self);
}

struct Bar;

impl Noise for Bar {
    fn noise(&self) {
        println!("bar bar bar");
    }
}

struct Baz;

impl Noise for Baz {
    fn noise(&self) {
        println!("baz baz baz");
    }
}

enum Foo {
    Bar(Bar),
    Baz(Baz),
}

impl Noise for Foo {
    fn noise(&self) {
        match self {
            Foo::Bar(bar) => bar.noise(),
            Foo::Baz(baz) => baz.noise(),
        }
    }
}

It's conceptually possible that the language could be extended to support some annotation to do this, but I've never heard of anyone suggesting it. You could consider creating an RFC to add it.

Perhaps you can go back to the source that taught you this and correct the problem at the root to prevent other peopl from being confused in the same manner.

See also:

  • Can traits be used on enum types?


来源:https://stackoverflow.com/questions/51661392/how-can-i-implement-a-trait-in-scope-for-an-enum-of-existing-types-for-which-the

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!