1use crate::region::Region;
2use crate::{GuestError, GuestPtr, GuestType};
3
4#[derive(Debug)]
5pub struct GuestBorrows {
6 borrows: Vec<Region>,
7}
8
9impl GuestBorrows {
10 pub fn new() -> Self {
11 Self {
12 borrows: Vec::new(),
13 }
14 }
15
16 fn is_borrowed(&self, r: Region) -> bool {
17 !self.borrows.iter().all(|b| !b.overlaps(r))
18 }
19
20 pub(crate) fn borrow(&mut self, r: Region) -> Result<(), GuestError> {
21 if self.is_borrowed(r) {
22 Err(GuestError::PtrBorrowed(r))
23 } else {
24 self.borrows.push(r);
25 Ok(())
26 }
27 }
28
29 pub fn borrow_pointee<'a, T>(&mut self, p: &GuestPtr<'a, T>) -> Result<(), GuestError>
33 where
34 T: GuestType<'a>,
35 {
36 self.borrow(Region {
37 start: p.offset(),
38 len: T::guest_size(),
39 })
40 }
41
42 pub fn borrow_slice<'a, T>(&mut self, p: &GuestPtr<'a, [T]>) -> Result<(), GuestError>
46 where
47 T: GuestType<'a>,
48 {
49 let (start, elems) = p.offset();
50 let len = T::guest_size()
51 .checked_mul(elems)
52 .ok_or_else(|| GuestError::PtrOverflow)?;
53 self.borrow(Region { start, len })
54 }
55
56 pub fn borrow_str(&mut self, p: &GuestPtr<str>) -> Result<(), GuestError> {
60 let (start, len) = p.offset();
61 self.borrow(Region { start, len })
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::*;
68 #[test]
69 fn nonoverlapping() {
70 let mut bs = GuestBorrows::new();
71 let r1 = Region::new(0, 10);
72 let r2 = Region::new(10, 10);
73 assert!(!r1.overlaps(r2));
74 bs.borrow(r1).expect("can borrow r1");
75 bs.borrow(r2).expect("can borrow r2");
76
77 let mut bs = GuestBorrows::new();
78 let r1 = Region::new(10, 10);
79 let r2 = Region::new(0, 10);
80 assert!(!r1.overlaps(r2));
81 bs.borrow(r1).expect("can borrow r1");
82 bs.borrow(r2).expect("can borrow r2");
83 }
84
85 #[test]
86 fn overlapping() {
87 let mut bs = GuestBorrows::new();
88 let r1 = Region::new(0, 10);
89 let r2 = Region::new(9, 10);
90 assert!(r1.overlaps(r2));
91 bs.borrow(r1).expect("can borrow r1");
92 assert!(bs.borrow(r2).is_err(), "cant borrow r2");
93
94 let mut bs = GuestBorrows::new();
95 let r1 = Region::new(0, 10);
96 let r2 = Region::new(2, 5);
97 assert!(r1.overlaps(r2));
98 bs.borrow(r1).expect("can borrow r1");
99 assert!(bs.borrow(r2).is_err(), "cant borrow r2");
100
101 let mut bs = GuestBorrows::new();
102 let r1 = Region::new(9, 10);
103 let r2 = Region::new(0, 10);
104 assert!(r1.overlaps(r2));
105 bs.borrow(r1).expect("can borrow r1");
106 assert!(bs.borrow(r2).is_err(), "cant borrow r2");
107
108 let mut bs = GuestBorrows::new();
109 let r1 = Region::new(2, 5);
110 let r2 = Region::new(0, 10);
111 assert!(r1.overlaps(r2));
112 bs.borrow(r1).expect("can borrow r1");
113 assert!(bs.borrow(r2).is_err(), "cant borrow r2");
114
115 let mut bs = GuestBorrows::new();
116 let r1 = Region::new(2, 5);
117 let r2 = Region::new(10, 5);
118 let r3 = Region::new(15, 5);
119 let r4 = Region::new(0, 10);
120 assert!(r1.overlaps(r4));
121 bs.borrow(r1).expect("can borrow r1");
122 bs.borrow(r2).expect("can borrow r2");
123 bs.borrow(r3).expect("can borrow r3");
124 assert!(bs.borrow(r4).is_err(), "cant borrow r4");
125 }
126}