Making an API more ergonimic

I have a type:

#[derive(Clone, Debug)]
pub enum Value {
    ...
    Int(i64),
    List(List),
    Map(Map),
    Real(f64),
    Str(String),
}

And some From functions, e.g.,

impl From<f32> for Value {
    fn from(f: f32) -> Self {
        Value::Real(f as f64)
    }
}
impl From<f64> for Value {
    fn from(f: f64) -> Self {
        Value::Real(f)
    }
}
impl From<&str> for Value {
    fn from(s: &str) -> Self {
        Value::Str(s.to_string())
    }
}
...

And this function:

impl Value {
    pub fn push(&mut self, value: Value) -> Result<()> {
        ...

So, given mut v of type Value::List, I can write: v.push(200.into()) and v.push("more".into()).

What I'd like to be able to do is #1: v.push(200) and v.push("more"); and #2 v.push_many(&[200, 100, 75]) and v.push_many(&["more", "some"]).

I could imagine I'd need a signature something like: fn push<T>(&mut self, values: &[T]) -> Result<()>, but how would I specify that T had to be of type Value?

That'd be values: &[Value]. But that's basically already what you have (except it's a single value, not a slice of them). So that's not what you want.

What you want is a generic function that asserts you can convert T into a Value, so you'd probably say T: Into<Value>.

1 Like

Well H2CO3 beat me to it, but here's a playground with the aforementioned suggestion to use T: Into<Value>:

1 Like

Thank you, I'm now using that :smile:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.