Как элегантно можно десериализовать массив, элементы которого разных типов?

Есть два файла. В первом содержится описание данных (вернее одного ряда, строки), а во втором сами данные.

1)

+--------------------------+-------------+-------------+...+-------------+-------------+
| Count of elements in row | Type (el#1) | Size (el#1) |   | Type (el#N) | Size (el#N) |
+--------------------------+-------------+-------------+...+-------------+-------------+
|           u32            |    i32      |     u32     |   |     i32     |     u32     |
+--------------------------+-------------+-------------+...+-------------+-------------+

Data file contains 2d array

+-----------+--------------+--------------+...+--------------+--------------+...
| Row count | (row 1) el#1 | (row 1) el#2 |   | (row 1) el#N | (row 2) el#1 |
+-----------+--------------+--------------+...+--------------+--------------+...
|    u32    |     РИС      |     РИС      |   |     РИС      |     РИС      |   
+-----------+--------------+--------------+...+--------------+--------------+...
*РИС - размер из схемы 

В общем, накидал я код, он, вроде как, работает, но мне не нравится, что в нём повторяется bincode::deserialize(bytes_slice).unwrap(). Мне это кажется странным. Можно ли более элегантно решить эту задачу? Может быть можно использовать только один enum?

use serde::Deserialize;

#[derive(Deserialize)]
struct SchemaUnit {
    size: u32,
    m_type: i32
}

enum SchemaType {
    U16,
    U32,
    U64,
    F32,
    F64,
    String
}

enum Datum {
    U16(u16),
    U32(u32),
    U64(u64),
    F32(f32),
    F64(f64),
    String(String)
}

impl SchemaType {
    fn from(num: i32) -> Option<Self> {
        match num {
            1 => Some(SchemaType::U16),
            2 => Some(SchemaType::U32),
            3 => Some(SchemaType::U64),
            7 => Some(SchemaType::F32),
            8 => Some(SchemaType::F64),
            19 => Some(SchemaType::String),
            _ => None
        }
    }
}

struct Data;

impl Data {
    fn from(bytes: Vec<u8>, schema: Vec<SchemaUnit>) -> Vec<Vec<Datum>> {
        let mut result: Vec<Vec<Datum>> = vec![];
        let row_count: u32 = bincode::deserialize(&bytes[..4]).unwrap();
        
        let size_of_row: u32 = schema.iter().map(|s| s.size).sum();
        
        let mut start = 4;

        for i in 0..row_count {
            let tmp: Vec<Datum> = vec![];
            for schema_unit in schema.iter() {
                let element_size = schema_unit.size as usize;
                let bytes_slice = &bytes[start..start + element_size];
                // TODO: handle types that doesn't exists 
                let m_type = SchemaType::from(schema_unit.m_type).unwrap();
                tmp.push(match m_type {
                    SchemaType::U16 => Datum::U16(bincode::deserialize(bytes_slice).unwrap()),
                    SchemaType::U32 => Datum::U32(bincode::deserialize(bytes_slice).unwrap()),
                    SchemaType::U64 => Datum::U64(bincode::deserialize(bytes_slice).unwrap()),
                    SchemaType::F32 => Datum::F32(bincode::deserialize(bytes_slice).unwrap()),
                    SchemaType::F64 => Datum::F64(bincode::deserialize(bytes_slice).unwrap()),
                    SchemaType::String => Datum::String(bytes_to_str(bytes_slice))
                });
                start += element_size;
            }
            result.push(tmp);
        }
        result
    }
}

Ответы (0 шт):