Предположим, у нас есть следующее перечисление:
#[derive(Serialize)]
#[serde(untagged)]
pub enum CustomType {
Foo(Foo),
Bar(Bar),
}
Чтобы иметь функцию, которая ведет себя одинаково для разных типов параметров:
fn my_function(my_param: &CustomType){
// logic to use "my_param"
// my_param is used for the handlebars crate, therefore requires to be Serde Serializable
let source = // ...
handlebars.render_template(&source, my_param).unwrap();
}
И мы хотим вызывать такую функцию в разных частях нашей программы следующим образом:
fn function_a(bar: &Bar){
my_function(CustomType::Bar(bar.clone()));
}
fn function_b(foo: &Foo){
my_function(CustomType::Foo(foo.clone()));
}
Этот код работает, но мне он очень не нравится, так как приходится .clone()
. Я уже пытался передать только ссылку, но для перечисления это не сработает.
Это правильный способ сделать это в Rust?
Вы можете заставить CustomType
брать ссылки вместо собственных значений, если не хотите вызывать clone
:
use serde::{Serialize};
#[derive(Serialize)]
struct Foo(String);
#[derive(Serialize)]
struct Bar(String);
#[derive(Serialize)]
#[serde(untagged)]
enum CustomType<'a> {
Foo(&'a Foo),
Bar(&'a Bar),
}
fn my_function(my_param: &CustomType) {
println!("serialized {}", serde_json::to_string(&my_param).unwrap());
}
fn func_foo(foo: &Foo) {
my_function(&CustomType::Foo(foo));
}
fn func_bar(bar: &Bar) {
my_function(&CustomType::Bar(bar));
}
fn main() {
let foo = Foo("Foo".to_string());
let bar = Bar("Bar".to_string());
func_foo(&foo);
func_bar(&bar);
}
Однако, если единственная причина существования CustomType
заключается в том, что вы можете передавать Serializable
типы в my_function
, то, вероятно, было бы проще просто сделать my_function
универсальным и принимать любые Serializable
ссылки:
use serde::{Serialize};
#[derive(Serialize)]
struct Foo(String);
#[derive(Serialize)]
struct Bar(String);
fn my_function<T: Serialize>(my_param: &T) {
println!("serialized {}", serde_json::to_string(my_param).unwrap());
}
fn main() {
let foo = Foo("Foo".to_string());
let bar = Bar("Bar".to_string());
my_function(&foo);
my_function(&bar);
}
Да! Причина
CustomType
была именно для этой цели. Я не знал, что вы можете просто<T: Serialize>
вещи (я пытался с<T>
раньше, но остановился, так как это не было сериализуемым)