1use serde::{Deserialize, Serialize};
9
10pub use pcode_types::space::{SPACE_CONST, Space, SpaceId, SpaceRef, SpaceStore, SpaceType};
11
12use crate::value::{FunctionId, LocalTempSpaceId, TempSpaceId};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum LocalMemorySpaceId {
17 Shared(SpaceId),
18 Temp(LocalTempSpaceId),
19}
20
21impl LocalMemorySpaceId {
22 pub const fn qualify(self, function: FunctionId) -> MemorySpaceId {
23 match self {
24 Self::Shared(id) => MemorySpaceId::Shared(id),
25 Self::Temp(local) => MemorySpaceId::Temp(TempSpaceId::new(function, local)),
26 }
27 }
28
29 pub const fn shared(self) -> Option<SpaceId> {
31 match self {
32 Self::Shared(id) => Some(id),
33 Self::Temp(_) => None,
34 }
35 }
36}
37
38impl From<SpaceId> for LocalMemorySpaceId {
39 fn from(id: SpaceId) -> Self {
40 Self::Shared(id)
41 }
42}
43
44impl PartialEq<SpaceId> for LocalMemorySpaceId {
45 fn eq(&self, other: &SpaceId) -> bool {
46 self.shared() == Some(*other)
47 }
48}
49
50impl PartialEq<LocalMemorySpaceId> for SpaceId {
51 fn eq(&self, other: &LocalMemorySpaceId) -> bool {
52 other == self
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
58pub enum MemorySpaceId {
59 Shared(SpaceId),
60 Temp(TempSpaceId),
61}
62
63impl MemorySpaceId {
64 pub fn localize(self, function: FunctionId) -> LocalMemorySpaceId {
65 match self {
66 Self::Shared(id) => LocalMemorySpaceId::Shared(id),
67 Self::Temp(id) => LocalMemorySpaceId::Temp(id.localize(function)),
68 }
69 }
70
71 pub const fn owning_function(self) -> Option<FunctionId> {
72 match self {
73 Self::Shared(_) => None,
74 Self::Temp(id) => Some(id.func),
75 }
76 }
77
78 pub const fn shared(self) -> Option<SpaceId> {
79 match self {
80 Self::Shared(id) => Some(id),
81 Self::Temp(_) => None,
82 }
83 }
84}
85
86impl From<SpaceId> for MemorySpaceId {
87 fn from(id: SpaceId) -> Self {
88 Self::Shared(id)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn temporary_memory_space_qualification_preserves_owner() {
98 let function = FunctionId::from(3);
99 let local = LocalTempSpaceId::from(4);
100 let qualified = LocalMemorySpaceId::Temp(local).qualify(function);
101
102 assert_eq!(
103 qualified,
104 MemorySpaceId::Temp(TempSpaceId::new(function, local))
105 );
106 assert_eq!(qualified.owning_function(), Some(function));
107 assert_eq!(
108 qualified.localize(function),
109 LocalMemorySpaceId::Temp(local)
110 );
111 assert_eq!(
112 MemorySpaceId::Shared(SpaceId::from(2)).owning_function(),
113 None
114 );
115 }
116
117 #[test]
118 #[cfg(debug_assertions)]
119 #[should_panic(expected = "TempSpaceId::localize: foreign id")]
120 fn temporary_memory_space_rejects_foreign_localization() {
121 MemorySpaceId::Temp(TempSpaceId::new(
122 FunctionId::from(1),
123 LocalTempSpaceId::from(0),
124 ))
125 .localize(FunctionId::from(2));
126 }
127}