Мне любопытно посмотреть, сколько шаблонной информации можно сэкономить с помощью встроенного отражения.
Небольшой фон
Моя идея, лежащая в основе структурированного ведения журналов, заключается в использовании различных небольших специализированных типов для разделения контентаиз представительства.Вместо неструктурированного logger.info("Found a bar with {} foos", bar.foo)
используется что-то вроде logger.info(FoundBar{ _bar: bar })
Мой подход Rust-ish
- определяет
Log
черту - , обеспечивающую реализацию по умолчанию, котораявызывает механизм Serde для сериализации типа (для JSON в этом примере)
- позволяет легко определить типы журналируемых объектов, позволяя им «наследовать» реализацию по умолчанию
- profit
Определите черту, предоставив значение по умолчанию:
trait Log {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}
(RLS уже рисует злые красные загогулины, но потерпите меня)
Определите простой тип для регистрации:
#[derive(Serialize)]
struct Message {
msg: String,
}
и пусть он использует реализацию по умолчанию:
impl Log for Message {}
и, наконец, функцию полиморфного ведения журнала, определенную в терминах признака:
fn log(log: &Log) {
println!("serialized = {}", log.to_log());
}
Компилятор жалуется:
error[E0277]: the trait bound `Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not satisfied
--> src\main.rs:8:9
|
8 | serde_json::to_string(&self).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not implemented for `Self`
|
= help: consider adding a `where Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` bound
= note: required because of the requirements on the impl of `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` for `&Self`
= note: required by `serde_json::ser::to_string`
Добавление предложения where Self
к моей функции черты приводит только к различным ошибкам (error[E0433]: failed to resolve. Use of undeclared type or module _IMPL_DESERIALIZE_FOR_Message
), но кроме этого кажется плохой идеей (TM), что эта деталь реализации утечки Serde в мойкод.
HКак я могу ограничить свою черту (используя where
?), чтобы она применялась только к типам, имеющим правильное наследование?Еще лучше, могу ли я «внедрить» производную функциональность в типы, используя черту?