vincent-herlemont / native_db

Drop-in embedded database in Rust
MIT License
433 stars 17 forks source link

ToKey implementation for Serializable types. #219

Closed majkrzak closed 12 hours ago

majkrzak commented 1 month ago

I have encountered a problem, where I wanted to use third-party type as a primary key. Thanks to Rust policy against orphans, it is not possible to implement ToKey trait for it.

As the type I wanted to use was serde compatible, I implemented generic ToKey for serde::Serialize types:

impl<T: Serialize + Debug> ToKey for T {
    fn to_key(&self) -> Key {
        let mut serializer = KeySerializer::new();
        self.serialize(&mut serializer).unwrap();
        serializer.into()
    }
}

Together with KeySerializer, which is backward compatible with the old implementation.

It covers wider range of types, and therefore some assumption how some types have to be processed were made. In particular enum types are serialized by their option indexes. This require from end-user to extend such types in specific way to keep backward compatibility.

Additionally, I believe, if this could ever made its way to the main branch following things have to be handled:

vincent-herlemont commented 1 month ago

Thank you very much, @majkrzak, for your suggestion. It's very interesting; however, I'm concerned that using Serde might create some overhead. I am currently working on improving the benchmarks to determine if such changes would cause any performance loss.

BTW, could you tell me a bit more about your initial problem? It is possible to use a type wrapper, for example with UUIDs here: struct Uuid(uuid::Uuid); src/db_type/key/key.rs#L76-L110. By using a type wrapper, you should normally be able to associate an interface with any third-party type.