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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#![feature(unsize)]
#![feature(unsafe_no_drop_flag,filling_drop)]
#![cfg_attr(feature="no_std",no_std)]
#![crate_type="lib"]
#![crate_name="stack_dst"]
#![deny(missing_docs)]
use std::{ops,mem,slice,marker,ptr};
#[cfg(feature="no_std")]
mod std {
pub use core::{ops,mem,slice,marker,ptr};
}
pub trait DataBuf: Copy+Default+AsMut<[usize]>+AsRef<[usize]> {
}
impl<T: Copy+Default+AsMut<[usize]>+AsRef<[usize]>> DataBuf for T {
}
pub const DEFAULT_SIZE: usize = 8+1;
pub type StackDST<T> = StackDSTA<T, [usize; DEFAULT_SIZE]>;
#[unsafe_no_drop_flag]
pub struct StackDSTA<T: ?Sized, D: DataBuf> {
_align: [u64; 0],
_pd: marker::PhantomData<T>,
data: D,
}
unsafe fn ptr_as_slice<'p, T: ?Sized>(ptr: &'p mut &T) -> &'p mut [usize] {
assert!( mem::size_of::<&T>() % mem::size_of::<usize>() == 0 );
let words = mem::size_of::<&T>() / mem::size_of::<usize>();
slice::from_raw_parts_mut(ptr as *mut &T as *mut usize, words)
}
unsafe fn as_ptr<T: ?Sized, D: DataBuf>(s: &StackDSTA<T, D>) -> *mut T {
let mut ret: &T = mem::zeroed();
{
let ret_as_slice = ptr_as_slice(&mut ret);
let data = s.data.as_ref();
ret_as_slice[0] = data[..].as_ptr() as usize;
let info_size = ret_as_slice.len() - 1;
let info_ofs = data.len() - info_size;
for i in 0 .. info_size {
ret_as_slice[1+i] = data[info_ofs + i];
}
}
ret as *const _ as *mut _
}
impl<T: ?Sized, D: DataBuf> StackDSTA<T, D>
{
pub fn new<U: marker::Unsize<T>>(val: U) -> Result<StackDSTA<T,D>,U> {
let rv = unsafe {
let mut ptr: &T = &val;
let words = ptr_as_slice(&mut ptr);
assert!(words[0] == &val as *const _ as usize, "BUG: Pointer layout is not (data_ptr, info...)");
assert!(mem::align_of::<U>() <= mem::align_of::<Self>(), "TODO: Enforce alignment >{} (requires {})",
mem::align_of::<Self>(), mem::align_of::<U>());
StackDSTA::new_raw(&words[1..], words[0] as *mut (), mem::size_of::<U>())
};
match rv
{
Some(r) => {
mem::forget(val);
Ok(r)
},
None => {
Err(val)
},
}
}
unsafe fn new_raw(info: &[usize], data: *mut (), size: usize) -> Option<StackDSTA<T,D>>
{
if info.len()*mem::size_of::<usize>() + size > mem::size_of::<D>() {
None
}
else {
let mut rv = StackDSTA {
_align: [],
_pd: marker::PhantomData,
data: D::default(),
};
assert!(info.len() + (size + mem::size_of::<usize>() - 1) / mem::size_of::<usize>() <= rv.data.as_ref().len());
{
let info_ofs = rv.data.as_ref().len() - info.len();
let info_dst = &mut rv.data.as_mut()[info_ofs..];
for (d,v) in Iterator::zip( info_dst.iter_mut(), info.iter() ) {
*d = *v;
}
}
let src_ptr = data as *const u8;
let dataptr = rv.data.as_mut()[..].as_mut_ptr() as *mut u8;
for i in 0 .. size {
*dataptr.offset(i as isize) = *src_ptr.offset(i as isize);
}
Some(rv)
}
}
}
impl<T: ?Sized, D: DataBuf> ops::Deref for StackDSTA<T, D> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*as_ptr(self)
}
}
}
impl<T: ?Sized, D: DataBuf> ops::DerefMut for StackDSTA<T, D> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *as_ptr(self)
}
}
}
impl<T: ?Sized, D: DataBuf> ops::Drop for StackDSTA<T, D> {
fn drop(&mut self) {
unsafe {
if self.data.as_ref()[ self.data.as_ref().len()-1 ] != mem::dropped::<usize>() {
ptr::drop_in_place(&mut **self)
}
}
}
}