turbofish-org / orga

Deterministic state machine engine written in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

EntryMap .range() cannot be called on derived Entry type

cwlittle opened this issue · comments

Initial testing of EntryMap included the following test struct:

    #[derive(Debug, Eq, PartialEq)]
    pub struct MapEntry {
        #[key]
        key: u32,
        value: u32,
    }

    impl Entry for MapEntry {
        type Key = u32;
        type Value = u32;

        fn into_entry(self) -> (Self::Key, Self::Value) {
            (self.key, self.value)
        }

        fn from_entry(entry: (Self::Key, Self::Value)) -> Self {
            MapEntry {
                key: entry.0,
                value: entry.1,
            }
        }
    }

However, derive Entry was implemented after EntryMap and while increasing code coverage in EntryMap, I noticed that it would be a bit cleaner to use the following:

    #[derive(Debug, Eq, PartialEq, Entry)]
    pub struct MapEntry {
        #[key]
        key: u32,
        value: u32,
    }

The expanded impl Entry block results in the following:

    impl ::orga::collections::Entry for MapEntry {
        type Key = (u32,); 
        type Value = (u32,); 

        fn into_entry(self) -> (Self::Key, Self::Value) { 
            ((self.key,), (self.value,),) 
        } 

        fn from_entry(item : (Self :: Key, Self :: Value)) -> Self{ 
            Self { key : item.0.0, value : item.1.0, } 
        }
    }

One reason this fails is that the underlying orga map requires that the key type, K, implement Next. Because Next isn't implemented for tuples, this fails. This is easy enough to solve with a declarative macro for tuples of any possible size where each element type also implements Next. However, this would mean that keys will be limited to 12 elements, but I don't see that need popping up very often.

Implementing Next for tuples generated by Entry derivation macro uncovered an edge case in the derivation macro. It isn't exactly apparent to the user that the derived Key and Value types from Entry will be tuples. Therefore, in the edge case that derived Key type is a 1-tuple, the expected EntryMap interaction API is broken. For example:

#[derive(Entry)]
struct MapEntry {
    #[key]
    key: u8,
    value: u32
}

let entry_map: EntryMap<MapEntry> = EntryMap::new();

// Expected API
for entry in entry_map.range(12..13) {
    ...
}

// Actual API
for entry in entry_map.range((12,)..(13,)) {
    ...
}

For 1-tuple key types, this derived Key should be the type of the key held in the 1-tuple. Tuples make enough sense for key types greater than or equal to 2 in the meantime.