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
use std::{collections::VecDeque, ops::{Deref, DerefMut}};
use crate::{context::{Global, Context}};
use super::{Svm};

/// Object that wraps, in some way, a pointer to SVM memory
/// # Safety
/// For an [`SvmPointer`] implementation to be safe, [`as_ptr`](SvmPointer::as_ptr) and [`as_mut_ptr`](SvmPointer::as_mut_ptr) must return the same SVM-allocated pointer.
pub unsafe trait SvmPointer<T: ?Sized> {
    type Context: Context;

    /// Returns a reference to the underlying [`Svm`] allocator
    fn allocator (&self) -> &Svm<Self::Context>;
    /// Returns the SVM pointer
    fn as_ptr (&self) -> *const T;
    /// Returns the mutable SVM pointer
    fn as_mut_ptr (&mut self) -> *mut T; 
    /// Returns the number of elements owned by the pointer
    fn len (&self) -> usize;
}

/// A [`Box`] with an [`Svm`] allocator
pub type SvmBox<T, C = Global> = Box<T, Svm<C>>;
/// A [`Vec`] with an [`Svm`] allocator
pub type SvmVec<T, C = Global> = Vec<T, Svm<C>>;
/// A [`VecDeque`] with an [`Svm`] allocator
pub type SvmVecDeque<T, C = Global> = VecDeque<T, Svm<C>>;

unsafe impl<T: ?Sized, C: Context> SvmPointer<T> for SvmBox<T, C> {
    type Context = C;

    #[inline(always)]
    fn allocator (&self) -> &Svm<C> {
        Box::allocator(self)
    }

    #[inline(always)]
    fn as_ptr (&self) -> *const T {
        self.deref()
    }

    #[inline(always)]
    fn as_mut_ptr (&mut self) -> *mut T {
        self.deref_mut()
    }

    #[inline(always)]
    fn len (&self) -> usize {
        1
    }
}

unsafe impl<T, C: Context> SvmPointer<T> for SvmBox<[T], C> {
    type Context = C;

    #[inline(always)]
    fn allocator (&self) -> &Svm<C> {
        Box::allocator(self)
    }

    #[inline(always)]
    fn as_ptr (&self) -> *const T {
        <[T]>::as_ptr(self)
    }

    #[inline(always)]
    fn as_mut_ptr (&mut self) -> *mut T {
        <[T]>::as_mut_ptr(self)
    }

    #[inline(always)]
    fn len (&self) -> usize {
        <[T]>::len(self)
    }
}

unsafe impl<T, C: Context> SvmPointer<T> for SvmVec<T, C> {
    type Context = C;

    #[inline(always)]
    fn allocator (&self) -> &Svm<C> {
        Vec::allocator(self)
    }

    #[inline(always)]
    fn as_ptr (&self) -> *const T {
        Vec::as_ptr(self)
    }

    #[inline(always)]
    fn as_mut_ptr (&mut self) -> *mut T {
        Vec::as_mut_ptr(self)
    }

    #[inline(always)]
    fn len (&self) -> usize {
        Vec::len(self)
    }
}

unsafe impl<T, C: Context> SvmPointer<[T]> for SvmVec<T, C> {
    type Context = C;

    #[inline(always)]
    fn allocator (&self) -> &Svm<C> {
        Vec::allocator(self)
    }

    #[inline(always)]
    fn as_ptr (&self) -> *const [T] {
        unsafe {
            core::slice::from_raw_parts(Vec::as_ptr(self), self.len())
        }
    }

    #[inline(always)]
    fn as_mut_ptr (&mut self) -> *mut [T] {
        unsafe {
            core::slice::from_raw_parts_mut(Vec::as_mut_ptr(self), self.len())
        }
    }

    #[inline(always)]
    fn len (&self) -> usize {
        1
    }
}