forked from nulang-org/nulang
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcapabilities.rs
More file actions
110 lines (99 loc) · 3.02 KB
/
Copy pathcapabilities.rs
File metadata and controls
110 lines (99 loc) · 3.02 KB
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
//! Capability system for controlling reference sharing.
use crate::types::Capability;
/// Compute the upper bound (join) of two capabilities in the lattice.
///
/// Lattice (highest to lowest permission):
/// Iso (isolated - unique mutable)
/// Trn (transition - unique but can become iso/ref)
/// Ref (reference - shared read/write)
/// Val (value - shared read-only, deeply immutable)
/// Box (boxed - unique ownership)
/// Tag (tag - no access, just identity)
pub fn cap_join(a: Capability, b: Capability) -> Capability {
use Capability::*;
match (a, b) {
// Tag is bottom
(Tag, c) | (c, Tag) => c,
// Iso is top
(Iso, _) | (_, Iso) => Iso,
// Val with anything stays Val (immutable)
(Val, Val) => Val,
(Val, _) | (_, Val) => Ref,
// Box + Box = Box, otherwise Trn
(Box, Box) => Box,
(Box, _) | (_, Box) => Trn,
// Trn + Trn = Trn, otherwise Ref
(Trn, Trn) => Trn,
(Trn, _) | (_, Trn) => Ref,
// Ref + Ref = Ref
(Ref, Ref) => Ref,
}
}
/// Compute the lower bound (meet) of two capabilities.
pub fn cap_meet(a: Capability, b: Capability) -> Capability {
use Capability::*;
match (a, b) {
(Iso, c) | (c, Iso) => c,
(Tag, _) | (_, Tag) => Tag,
(Box, Box) => Box,
(Box, _) | (_, Box) => Tag,
(Trn, Trn) => Trn,
(Trn, Val) | (Val, Trn) => Val,
(Trn, _) | (_, Trn) => Tag,
(Val, Val) => Val,
(Val, _) | (_, Val) => Val,
(Ref, Ref) => Ref,
}
}
/// Can a read be performed with the given capability?
pub fn can_read(cap: Capability) -> bool {
use Capability::*;
matches!(cap, Iso | Trn | Ref | Val | Box)
}
/// Can a write be performed with the given capability?
pub fn can_write(cap: Capability) -> bool {
use Capability::*;
matches!(cap, Iso | Trn | Ref)
}
/// Can the reference be aliased (shared)?
pub fn can_alias(cap: Capability) -> bool {
use Capability::*;
matches!(cap, Val | Ref | Tag)
}
/// Is the reference sendable across actors?
pub fn can_send(cap: Capability) -> bool {
use Capability::*;
matches!(cap, Iso | Val | Tag)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cap_join() {
use Capability::*;
assert_eq!(cap_join(Tag, Ref), Ref);
assert_eq!(cap_join(Val, Val), Val);
assert_eq!(cap_join(Val, Iso), Iso);
assert_eq!(cap_join(Box, Box), Box);
assert_eq!(cap_join(Box, Trn), Trn);
}
#[test]
fn test_cap_meet() {
use Capability::*;
assert_eq!(cap_meet(Iso, Ref), Ref);
assert_eq!(cap_meet(Val, Val), Val);
assert_eq!(cap_meet(Box, Trn), Tag);
}
#[test]
fn test_permissions() {
use Capability::*;
assert!(can_read(Ref));
assert!(can_write(Ref));
assert!(!can_write(Val));
assert!(can_alias(Val));
assert!(!can_alias(Box));
assert!(can_send(Iso));
assert!(can_send(Val));
assert!(!can_send(Ref));
}
}