use super::*;

pub struct Blobs {
    map: HashMap<Vec<u8>, u32>,
    stream: Vec<u8>,
}

impl Default for Blobs {
    fn default() -> Self {
        Self { map: Default::default(), stream: vec![0] }
    }
}

impl Blobs {
    pub fn insert(&mut self, value: &[u8]) -> u32 {
        if value.is_empty() {
            return 0;
        }

        match self.map.entry(value.to_vec()) {
            std::collections::hash_map::Entry::Vacant(entry) => {
                let offset = *entry.insert(self.stream.len() as u32);
                let len = value.len();
                match len {
                    0..=0x7F => self.stream.push(len as u8),
                    0x80..=0x3FFF => {
                        self.stream.push((0x80 | len >> 8) as u8);
                        self.stream.push((0xFF & len) as u8);
                    }
                    _ => {
                        self.stream.push((0xC0 | len >> 24) as u8);
                        self.stream.push((0xFF & len >> 16) as u8);
                        self.stream.push((0xFF & len >> 8) as u8);
                        self.stream.push((0xFF & len) as u8);
                    }
                }
                self.stream.extend_from_slice(value);
                offset
            }
            std::collections::hash_map::Entry::Occupied(entry) => *entry.get(),
        }
    }

    pub fn into_stream(self) -> Vec<u8> {
        self.stream.into_stream()
    }
}
