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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use std::{
    fmt::{self, Debug},
    hash::Hash,
    panic::Location,
};

#[derive(Clone, Copy)]
pub struct CallId {
    pub(crate) loc: &'static Location<'static>,
}

impl CallId {
    fn loc_ptr(&self) -> *const Location<'static> {
        self.loc
    }
}

impl From<&'static Location<'static>> for CallId {
    fn from(loc: &'static Location<'static>) -> Self {
        CallId { loc }
    }
}

impl Debug for CallId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!(
            "{}:{}:{}",
            self.loc.file(),
            self.loc.line(),
            self.loc.column()
        ))
    }
}

impl PartialEq for CallId {
    fn eq(&self, other: &CallId) -> bool {
        self.loc_ptr() == other.loc_ptr()
    }
}

impl Eq for CallId {}

impl Hash for CallId {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.loc_ptr().hash(state)
    }
}

impl PartialOrd for CallId {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.loc_ptr().partial_cmp(&other.loc_ptr())
    }
}

impl Ord for CallId {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.loc_ptr().cmp(&other.loc_ptr())
    }
}

#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct SlotId {
    pub call_id: CallId,
    pub key: Option<usize>,
}

impl SlotId {
    pub fn new(call_id: impl Into<CallId>, key: impl Into<Option<usize>>) -> Self {
        Self {
            call_id: call_id.into(),
            key: key.into(),
        }
    }
}

impl From<&'static Location<'static>> for SlotId {
    fn from(loc: &'static Location<'static>) -> Self {
        SlotId::new(loc, None)
    }
}

impl Debug for SlotId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.alternate() {
            match self.key {
                Some(key) => f.write_fmt(format_args!("{:#?} |{}", self.call_id, key)),
                None => f.write_fmt(format_args!("{:#?} |*", self.call_id)),
            }
        } else {
            match self.key {
                Some(key) => f.write_fmt(format_args!("{:?} |{}", self.call_id, key)),
                None => f.write_fmt(format_args!("{:?} |*", self.call_id)),
            }
        }
    }
}

pub struct Slot<T> {
    pub id: SlotId,
    pub size: usize,
    pub data: Option<T>,
}

impl<T> Slot<T> {
    pub fn new(slot_id: SlotId, data: T) -> Self {
        Slot {
            id: slot_id,
            data: Some(data),
            size: 1,
        }
    }

    pub fn placeholder(slot_id: SlotId) -> Self {
        Slot {
            id: slot_id,
            data: None,
            size: 1,
        }
    }
}

impl<T: Debug> Debug for Slot<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut s = f.debug_struct("Slot");
        s.field("id", &self.id);
        s.field("data", &self.data);
        if self.size > 1 {
            s.field("size", &self.size);
        }
        s.finish()
    }
}