kawasin73 / prsqlite

Pure Rust implementation of SQLite
Apache License 2.0
563 stars 23 forks source link

new HashMap implementation: the key is the reference of value. #10

Open kawasin73 opened 1 year ago

kawasin73 commented 1 year ago

The table map consider the table name as case insensitive.

The table map in Schema is tables: HashMap<Vec<u8>, Table> which requires the table name to be cloned and clone the search key on finding as well.

The search part can be mitigated by using new UpperToLowerBytes. However it requires unsafe to convert &[u8] to &UpperToLowerBytes. also it still clones the key on insersion.

#[derive(Eq)]
pub struct UpperToLowerBytesVec(Vec<u8>);

impl UpperToLowerBytesVec {
    pub fn new(bytes: Vec<u8>) -> Self {
        Self(bytes)
    }
}

impl Borrow<UpperToLowerBytes> for UpperToLowerBytesVec {
    fn borrow(&self) -> &UpperToLowerBytes {
        (&self.0[..]).into()
    }
}

impl PartialEq for UpperToLowerBytesVec {
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0
    }
}

#[derive(Eq)]
pub struct UpperToLowerBytes([u8]);

impl From<&[u8]> for &UpperToLowerBytes {
    fn from(bytes: &[u8]) -> Self {
        unsafe { &*(bytes as *const [u8] as *const UpperToLowerBytes) }
    }
}

impl PartialEq for UpperToLowerBytes {
    fn eq(&self, other: &Self) -> bool {
        if self.0.len() != other.0.len() {
            return false;
        }
        for (i, b) in self.0.iter().enumerate() {
            if UPPER_TO_LOWER[*b as usize] != UPPER_TO_LOWER[other.0[i] as usize] {
                return false;
            }
        }
        true
    }
}

impl Hash for UpperToLowerBytes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for b in self.0.iter() {
            state.write_u8(UPPER_TO_LOWER[*b as usize]);
        }
    }
}

Let's implement a new hash map using a key from the value.