застрял.
есть трейт DataType для сериалайзеров/десериалайзеров (Int, Str, DateTime) растовых типов данных в набор байт:
pub trait DataType<T> {
fn new(value: T) -> Self
where Self: Sized;
fn from_(raw: &[u8]) -> Self
where Self: Sized;
fn deserialize(raw: &[u8]) -> T
where Self: Sized;
fn get(&self) -> T;
fn serialize(&self) -> Box<[u8]>;
}
#[derive(Debug, Clone)]
pub struct Int {
value: i32,
}
impl DataType<i32> for Int {
fn new(value: i32) -> Self { Self {value} }
fn from_(raw: &[u8]) -> Int { Self {value: Int::deserialize(raw)}}
fn deserialize(raw: &[u8]) -> i32 { i32::from_ne_bytes(raw.try_into().unwrap_or([0, 0, 0, 0])) }
fn get(&self) -> i32 { self.value.clone() }
fn serialize(&self) -> Box<[u8]> { self.value.to_ne_bytes().into() }
}
#[derive(Debug, Clone)]
pub struct Str {
value: String,
}
impl DataType<String> for Str { /* ... */ }
#[derive(Debug, Clone)]
pub struct DateTime {
value: chrono::NaiveDateTime,
}
impl DataType<chrono::NaiveDateTime> for DateTime { /* ... */ }
Сами DataType используются в таблицах:
#[derive(TableSchema, Debug)]
pub struct SomeTable {
pub id: Int,
pub name: Str,
}
impl SomeTable {
// ...
fn get<T>(&self, field: String) -> Option<Box<impl DataType<T>>> {
match field.as_str() {
"id" => Some(Box::<Int>::new(self.id.clone())),
"name" => Some(Box::<Str>::new(self.name.clone())),
_ => None
}
}
}
Метод get нужен, чтобы в рантайме достать значение поля по ключу. Но компилятор, похоже, ругается на дженерик в DataType:
error[E0277]: the trait bound `Int: DataType<T>` is not satisfied
--> playground/src/schemas.rs:31:40
|
31 | fn get<T>(&self, field: String) -> Option<Box<impl DataType<T>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DataType<T>` is not implemented for `Int`
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
30 | impl SomeTable where Int: DataType<T> {
Что я делаю не так? :с
Как можно вернуть любые реализации DataType из get?
Я понимаю, что это не имеет отношения к твоему проекту, но.. а че не disel?
лабка в универе)
Он говорит, что Int реализует только DataType<i32>, а не для всех T. Возвращаемый тип должен быть статически известен во всех случаях. Возможно, тебе придётся избавиться от T в DataType.
> Возможно, тебе придётся избавиться от T в DataType. тоже было такое намерение, но хз как реализовать. 1. но как тогда хранить тип (i32, String, ...)? добавлять его как дженерик <T> в каждую структуру (а не трейт), с type: PhantomData<T>? 1.1. в трейте пропадёт возможность обозначить абстрактные fn new(value: T) -> Self и fn get(&self) -> T;. я вечером ещё почитаю про enum'ы, спасибо за идею!)
Обсуждают сегодня