Thermatix
Thermatix

Reputation: 2929

rust says trait From<i32> isn't implimented

I've got an enum:

#[derive(PartialEq, Debug)]
pub enum EventValue {
    Numeric(i32),
    Bool(bool),
    Text(String),
}

And it's used in a Vec which is used in a HashMap:

type Events = Vec<Event>;
pub type Stream = HashMap<String, Events>;

and I've implemented the From trait on it for i32 (and the other three types):

impl From<i32> for EventValue {
    fn from(v: i32) -> Self {
        EventValue::Numeric(v)
    }
}

impl From<String> for EventValue {
    fn from(v: String) -> Self {
        EventValue::Text(v)
    }
}

impl From<bool> for EventValue {
    fn from(v: bool) -> Self {
        EventValue::Bool(v)
    }
}

but when I try to use it in a function:

let motions = event_stream.get_channel("motions"); // << return a Vec
for motion in motions.drain(0..) {
    let amount: i32 = motion.value.into(); // <-- here is where I get the error
    // .. do somthing with amount
}

I get this error:

the trait bound `i32: std::convert::From<prelude::game::entity::components::event_stream::EventValue>` is not satisfied
  --> src/game/system/entity/movement.rs:17:48
   |
17 |                 let amount: i32 = motion.value.into();
   |                                                ^^^^ the trait `std::convert::From<prelude::game::entity::components::event_stream::EventValue>` is not implemented for `i32`
   |
   = help: the following implementations were found:
             <i32 as std::convert::From<bool>>
             <i32 as std::convert::From<i16>>
             <i32 as std::convert::From<i8>>
             <i32 as std::convert::From<std::num::NonZeroI32>>
           and 2 others
   = note: required because of the requirements on the impl of `std::convert::Into<i32>` for `prelude::game::entity::components::event_stream::EventValue`

What have I missed?

Bonus:

It's possible to build a function that auto converts incoming values for you provided you implement From like this:


impl Event {
    pub fn new<V: Into<EventValue>>(message: String, value: V) -> Event {
        Self {
            message: message,
            value: value.into(),
        }
    }
}

Is it possible to create a function that can do the same thing but for returning a value?

Upvotes: 1

Views: 1412

Answers (1)

SCappella
SCappella

Reputation: 10434

The error says that From<EventValue> isn't implemented for i32, not that From<i32> isn't implemented for EventValue. With the fully qualified names, it's a little harder to read, but that's what

the trait bound i32: std::convert::From<prelude::game::entity::components::event_stream::EventValue> is not satisfied

is saying.

The problem is that you're going the wrong direction. You've implemented the conversion i32 -> EventValue, but not EventValue -> i32, which is what your sample code is trying to do.

You'll probably want to match on the value instead and handle not only the Numeric case, but also the Bool and Text cases.

let motions = event_stream.get_channel("motions"); // << return a Vec
for motion in motions.drain(0..) {
    match motion.value {
        Numeric(value) => {// handle `Numeric` case},
        Bool(value) => {// handle `Bool` case},
        Text(text) => {// handle `Text` case},
    }
}

motion.value could be any of those three variants, so you can't assume it'll always be convertible to i32.

Upvotes: 5

Related Questions