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?