I want to build a system where data of different types (i32
, String
, ...) flows between functions that modify the data. For example, I want to have an add
function that gets "some" data and adds it.
The add
function gets something of type Value
and if Value
is an i32
, it adds the two i32
values, if it is of type String
, it returns a string that combines both strings.
I know that this would be almost perfect for template programming (or whatever this is called in Rust, I'm coming from C++) but in my case I want to have small code blocks that handle the stuff.
As an example, with f64
and String
, using Float
and Text
as the names, I have:
pub struct Float {
pub min: f64,
pub max: f64,
pub value: f64,
}
pub struct Text {
pub value: String,
}
pub enum Value {
Float(Float),
Text(Text),
}
Now I want to implement a function that gets a value that is supposed to be a string and does something to it, so I implement the to_string()
method for Value
:
impl std::string::ToString for Value {
fn to_string(&self) -> String {
match self {
Value::Float(f) => format!("{}", f.value).to_string(),
Value::Text(t) => t.value.clone(),
}
}
}
Now the function would do something like:
fn do_something(value: Value) -> Value {
let s = value.to_string();
// do something with s, which probably leads to creating a new string
let new_value = Text(new_string);
Value::Text(new_value)
}
In the case of a Value::Float
this would create a new String
, then a new String
with the result and return it, but in the case of a Value::Text
this would clone the string, which is an unnecessary step, and then create the new one.
Is there a way where the to_string()
implementation could create a new String
on Value::Float
but return the reference of Value::Text
's value?