use crate::permission::Permission;
use std::marker::PhantomData;
#[must_use = "capability tokens are proof of permission — discarding one wastes a grant"]
pub struct Cap<P: Permission> {
_phantom: PhantomData<P>,
_not_send: PhantomData<*const ()>,
}
impl<P: Permission> Cap<P> {
pub(crate) fn new() -> Self {
Self {
_phantom: PhantomData,
_not_send: PhantomData,
}
}
#[doc(hidden)]
pub fn __capsec_new_derived(_seal: crate::__private::SealProof) -> Self
where
P: Permission<__CapsecSeal = crate::__private::SealProof>,
{
Self {
_phantom: PhantomData,
_not_send: PhantomData,
}
}
#[must_use = "make_send consumes the original Cap and returns a SendCap"]
pub fn make_send(self) -> SendCap<P> {
SendCap {
_phantom: PhantomData,
}
}
}
impl<P: Permission> Clone for Cap<P> {
fn clone(&self) -> Self {
Cap::new()
}
}
#[must_use = "capability tokens are proof of permission — discarding one wastes a grant"]
pub struct SendCap<P: Permission> {
_phantom: PhantomData<P>,
}
unsafe impl<P: Permission> Send for SendCap<P> {}
unsafe impl<P: Permission> Sync for SendCap<P> {}
impl<P: Permission> SendCap<P> {
#[doc(hidden)]
pub fn __capsec_new_send_derived(_seal: crate::__private::SealProof) -> Self
where
P: Permission<__CapsecSeal = crate::__private::SealProof>,
{
Self {
_phantom: PhantomData,
}
}
pub fn as_cap(&self) -> Cap<P> {
Cap::new()
}
}
impl<P: Permission> Clone for SendCap<P> {
fn clone(&self) -> Self {
SendCap {
_phantom: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::permission::FsRead;
use std::mem::size_of;
#[test]
fn cap_is_zst() {
assert_eq!(size_of::<Cap<FsRead>>(), 0);
}
#[test]
fn sendcap_is_zst() {
assert_eq!(size_of::<SendCap<FsRead>>(), 0);
}
#[test]
fn cap_is_cloneable() {
let root = crate::root::test_root();
let cap = root.grant::<FsRead>();
let _cap2 = cap.clone();
}
#[test]
fn sendcap_crosses_threads() {
let root = crate::root::test_root();
let send_cap = root.grant::<FsRead>().make_send();
std::thread::spawn(move || {
let _cap = send_cap.as_cap();
})
.join()
.unwrap();
}
}