1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use fnv::FnvHashMap as HashMap;

use crate::{
    error::{anyhow, Result},
    ty::Type,
};

type TypeId = u32;

#[derive(Default)]
pub struct TypeRegistry {
    ty_map: HashMap<TypeId, Type>,
}
impl TypeRegistry {
    /// Allocate a type handle referred by `ty_id` and optionally assign a type
    /// to it.
    pub fn set(&mut self, id: TypeId, ty: Type) -> Result<()> {
        use std::collections::hash_map::Entry;
        match self.ty_map.entry(id) {
            Entry::Vacant(entry) => {
                entry.insert(ty);
                Ok(())
            }
            Entry::Occupied(mut entry) => {
                if entry.get().is_device_address() && ty.is_device_pointer() {
                    entry.insert(ty);
                    Ok(())
                } else {
                    Err(anyhow!(
                        "type collision at id {}: {:?} vs {:?}",
                        id,
                        entry.get(),
                        ty
                    ))
                }
            }
        }
    }

    /// Get the type identified by `handle`.
    pub fn get(&self, id: TypeId) -> Result<&Type> {
        self.ty_map
            .get(&id)
            .ok_or(anyhow!("missing type id {}", id))
    }
}