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
#![no_std]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(unique)]
extern crate loca;
use core::mem;
use core::ops::{ Deref, DerefMut };
use core::ptr::{ self, Unique };
use loca::*;
#[cfg_attr(not(test), lang = "owned_box")]
#[fundamental]
pub struct Box<T: ?Sized, A: Alloc> {
ptr: Unique<T>,
alloc: A,
}
impl<T, A: Alloc> Box<T, A> {
#[inline]
pub fn new_in(mut a: A, x: T) -> Result<Self, T> {
if 0 == mem::size_of::<T>() { Ok(Unique::empty()) } else { match a.alloc_one() {
Ok(ptr) => unsafe { ptr::write(ptr.as_ptr(), x); Ok(ptr) },
Err(_) => Err(x),
} }.map(|ptr| Box { ptr: ptr, alloc: a })
}
}
impl<T, A: Alloc + Default> Box<T, A> {
#[inline]
pub fn new(x: T) -> Result<Self, T> { Self::new_in(A::default(), x) }
}
impl<T: ?Sized, A: Alloc> Box<T, A> {
#[inline]
pub unsafe fn from_raw_in(a: A, ptr: *mut T) -> Self { Box { ptr: Unique::new_unchecked(ptr), alloc: a } }
#[inline]
pub unsafe fn into_raw(self) -> *mut T { self.ptr.as_ptr() }
}
impl<T: ?Sized, A: Alloc + Default> Box<T, A> {
#[inline]
pub unsafe fn from_raw(ptr: *mut T) -> Self { Self::from_raw_in(A::default(), ptr) }
}
impl<T: ?Sized, A: Alloc> Deref for Box<T, A> {
type Target = T;
fn deref(&self) -> &T { unsafe { self.ptr.as_ref() } }
}
impl<T: ?Sized, A: Alloc> DerefMut for Box<T, A> {
fn deref_mut(&mut self) -> &mut T { unsafe { self.ptr.as_mut() } }
}
impl<T: ?Sized, A: Alloc> Drop for Box<T, A> {
fn drop(&mut self) {
if 0 != mem::size_of_val(self.deref()) { unsafe {
ptr::drop_in_place(self.ptr.as_ptr());
self.alloc.dealloc(self.ptr.as_ptr() as _, Layout::for_value(self.ptr.as_ref()));
} }
}
}
#[cfg(test)] mod tests {
extern crate default_allocator;
use core::{mem, ptr};
use core::ops::Deref;
type Box<T> = super::Box<T, default_allocator::Heap>;
#[test]
fn drop() {
struct T<'a>(&'a mut bool);
impl<'a> Drop for T<'a> {
fn drop(&mut self) {
*self.0 = true;
}
}
let mut c = false;
{
let _ = Box::new(T(&mut c));
}
assert!(c);
}
#[test]
fn keeps_value() {
let mut b = Box::new(0).unwrap();
assert_eq!(0, *b);
*b += 1;
assert_eq!(1, *b);
}
#[test]
fn zero_size() {
let b = Box::new(()).unwrap();
assert_eq!((), *b);
assert_ne!(ptr::null(), &b as *const _);
b.deref();
mem::forget(b);
}
}