This moves the raw struct layout of closures, vectors, boxes, and strings into a
new `unstable::raw` module. This is meant to be a centralized location to find
information for the layout of these values.
As safe method, `repr`, is provided to convert a rust value to its raw
representation. Unsafe methods to convert back are not provided because they are
rarely used and too numerous to write an implementation for each (not much of a
common pattern).
//! Managed vectors
-use cast::transmute;
use clone::Clone;
use container::Container;
use iterator::IteratorUtil;
use option::Option;
use sys;
use uint;
+use unstable::raw::Repr;
use vec::{ImmutableVector, OwnedVector};
/// Code for dealing with @-vectors. This is pretty incomplete, and
#[inline]
pub fn capacity<T>(v: @[T]) -> uint {
unsafe {
- let repr: **raw::VecRepr = transmute(&v);
- (**repr).unboxed.alloc / sys::size_of::<T>()
+ let box = v.repr();
+ (*box).data.alloc / sys::size_of::<T>()
}
}
*/
#[inline]
pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] {
- let mut vec: @[A] = @[];
+ let mut vec = @[];
unsafe { raw::reserve(&mut vec, size); }
builder(|x| unsafe { raw::push(&mut vec, x) });
- return unsafe { transmute(vec) };
+ vec
}
/**
for v.consume_iter().advance |x| {
raw::push(&mut av, x);
}
- transmute(av)
+ av
}
}
use ptr;
use sys;
use uint;
- use unstable::intrinsics;
use unstable::intrinsics::{move_val_init, TyDesc};
- use vec;
- use vec::UnboxedVecRepr;
-
- pub type VecRepr = vec::raw::VecRepr;
- pub type SliceRepr = vec::raw::SliceRepr;
+ use unstable::intrinsics;
+ use unstable::raw::{Box, Vec};
/**
* Sets the length of a vector
* the vector is actually the specified size.
*/
#[inline]
- pub unsafe fn set_len<T>(v: @[T], new_len: uint) {
- let repr: **mut VecRepr = transmute(&v);
- (**repr).unboxed.fill = new_len * sys::size_of::<T>();
+ pub unsafe fn set_len<T>(v: &mut @[T], new_len: uint) {
+ let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
+ (*repr).data.fill = new_len * sys::size_of::<T>();
}
/**
*/
#[inline]
pub unsafe fn push<T>(v: &mut @[T], initval: T) {
- let repr: **VecRepr = transmute_copy(&v);
- let fill = (**repr).unboxed.fill;
- if (**repr).unboxed.alloc > fill {
+ let full = {
+ let repr: *Box<Vec<T>> = cast::transmute_copy(v);
+ (*repr).data.alloc > (*repr).data.fill
+ };
+ if full {
push_fast(v, initval);
} else {
push_slow(v, initval);
#[inline] // really pretty please
unsafe fn push_fast<T>(v: &mut @[T], initval: T) {
- let repr: **mut VecRepr = ::cast::transmute(v);
- let fill = (**repr).unboxed.fill;
- (**repr).unboxed.fill += sys::size_of::<T>();
- let p = &((**repr).unboxed.data);
- let p = ptr::offset(p, fill) as *mut T;
+ let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
+ let amt = v.len();
+ (*repr).data.fill += sys::size_of::<T>();
+ let p = ptr::offset(&(*repr).data.data as *T, amt) as *mut T;
move_val_init(&mut(*p), initval);
}
unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
- reserve_at_least(&mut *v, v.len() + 1u);
+ reserve_at_least(v, v.len() + 1u);
push_fast(v, initval);
}
pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
// Only make the (slow) call into the runtime if we have to
if capacity(*v) < n {
- let ptr: *mut *mut VecRepr = transmute(v);
+ let ptr: *mut *mut Box<Vec<()>> = transmute(v);
let ty = intrinsics::get_tydesc::<T>();
// XXX transmute shouldn't be necessary
let ty = cast::transmute(ty);
// Implementation detail. Shouldn't be public
#[allow(missing_doc)]
- pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut VecRepr, n: uint) {
+ pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
unsafe {
let size_in_bytes = n * (*ty).size;
- if size_in_bytes > (**ptr).unboxed.alloc {
- let total_size = size_in_bytes + sys::size_of::<UnboxedVecRepr>();
- // XXX: UnboxedVecRepr has an extra u8 at the end
- let total_size = total_size - sys::size_of::<u8>();
- (*ptr) = local_realloc(*ptr as *(), total_size) as *mut VecRepr;
- (**ptr).unboxed.alloc = size_in_bytes;
+ if size_in_bytes > (**ptr).data.alloc {
+ let total_size = size_in_bytes + sys::size_of::<Vec<()>>();
+ (*ptr) = local_realloc(*ptr as *(), total_size) as *mut Box<Vec<()>>;
+ (**ptr).data.alloc = size_in_bytes;
}
}
#[cfg(test)]
mod tests {
use cast::{bump_box_refcount, transmute};
+ use unstable::raw;
#[test]
fn test_transmute_copy() {
#[test]
fn test_transmute() {
- use managed::raw::BoxRepr;
unsafe {
let x = @100u8;
- let x: *BoxRepr = transmute(x);
+ let x: *raw::Box<u8> = transmute(x);
assert!((*x).data == 100);
let _x: @int = transmute(x);
}
use libc::c_void;
use ptr::{mut_null};
-use repr::BoxRepr;
use unstable::intrinsics::TyDesc;
+use unstable::raw;
type DropGlue<'self> = &'self fn(**TyDesc, *c_void);
}
unsafe fn each_live_alloc(read_next_before: bool,
- f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) -> bool {
+ f: &fn(box: *mut raw::Box<()>, uniq: bool) -> bool) -> bool {
//! Walks the internal list of allocations
use managed;
use rt::local_heap;
- let box = local_heap::live_allocs();
- let mut box: *mut BoxRepr = transmute(box);
+ let mut box = local_heap::live_allocs();
while box != mut_null() {
let next_before = (*box).next;
let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE;
if uniq {
stats.n_unique_boxes += 1;
} else {
- (*box).header.ref_count = managed::raw::RC_IMMORTAL;
+ (*box).ref_count = managed::RC_IMMORTAL;
}
}
for each_live_alloc(true) |box, uniq| {
if !uniq {
stats.n_bytes_freed +=
- (*((*box).header.type_desc)).size
- + sys::size_of::<BoxRepr>();
- local_free(box as *u8);
+ (*((*box).type_desc)).size
+ + sys::size_of::<raw::Box<()>>();
+ local_free(box as *i8);
}
}
#[cfg(not(test))] use cmp::{Eq, Ord};
-pub mod raw {
- use std::unstable::intrinsics::TyDesc;
-
- pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
- pub static RC_IMMORTAL : uint = 0x77777777;
-
- #[allow(missing_doc)]
- pub struct BoxHeaderRepr {
- ref_count: uint,
- type_desc: *TyDesc,
- prev: *BoxRepr,
- next: *BoxRepr,
- }
-
- #[allow(missing_doc)]
- pub struct BoxRepr {
- header: BoxHeaderRepr,
- data: u8
- }
-
-}
+pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
+pub static RC_IMMORTAL : uint = 0x77777777;
/// Determine if two shared boxes point to the same object
#[inline]
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
use libc::c_void;
use sys;
-use vec;
+use unstable::raw;
/**
* Trait for visitor that wishes to reflect on data. To use this, create a
}
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
- self.align_to::<vec::UnboxedVecRepr>();
+ self.align_to::<raw::Vec<()>>();
if ! self.inner.visit_vec(mtbl, inner) { return false; }
true
}
use io::{Writer, WriterUtil};
use iterator::IteratorUtil;
use libc::c_void;
-use managed;
use ptr;
use reflect;
use reflect::{MovePtr, align};
use str::StrSlice;
use to_str::ToStr;
-use vec::raw::{VecRepr, SliceRepr};
-use vec;
-use vec::{OwnedVector, UnboxedVecRepr};
+use vec::OwnedVector;
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
+use unstable::raw;
#[cfg(test)] use io;
-pub use managed::raw::BoxRepr;
-
/// Helpers
trait EscapedCharWriter {
pub fn write_vec_range(&self,
_mtbl: uint,
- ptr: *u8,
+ ptr: *(),
len: uint,
inner: *TyDesc)
-> bool {
- let mut p = ptr;
+ let mut p = ptr as *u8;
let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
self.writer.write_char('[');
let mut first = true;
pub fn write_unboxed_vec_repr(&self,
mtbl: uint,
- v: &UnboxedVecRepr,
+ v: &raw::Vec<()>,
inner: *TyDesc)
-> bool {
self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.writer.write_char('@');
self.write_mut_qualifier(mtbl);
- do self.get::<&managed::raw::BoxRepr> |b| {
+ do self.get::<&raw::Box<()>> |b| {
let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
self.visit_ptr_inner(p, inner);
}
fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
self.writer.write_char('~');
- do self.get::<&managed::raw::BoxRepr> |b| {
+ do self.get::<&raw::Box<()>> |b| {
let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
self.visit_ptr_inner(p, inner);
}
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<vec::UnboxedVecRepr> |b| {
+ do self.get::<raw::Vec<()>> |b| {
self.write_unboxed_vec_repr(mtbl, b, inner);
}
}
fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<&VecRepr> |b| {
+ do self.get::<&raw::Box<raw::Vec<()>>> |b| {
self.writer.write_char('@');
self.write_mut_qualifier(mtbl);
- self.write_unboxed_vec_repr(mtbl, &b.unboxed, inner);
+ self.write_unboxed_vec_repr(mtbl, &b.data, inner);
}
}
fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<&UnboxedVecRepr> |b| {
+ do self.get::<&raw::Vec<()>> |b| {
self.writer.write_char('~');
self.write_unboxed_vec_repr(mtbl, *b, inner);
}
}
fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<&VecRepr> |b| {
+ do self.get::<&raw::Box<raw::Vec<()>>> |b| {
self.writer.write_char('~');
- self.write_unboxed_vec_repr(mtbl, &b.unboxed, inner);
+ self.write_unboxed_vec_repr(mtbl, &b.data, inner);
}
}
fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<SliceRepr> |s| {
+ do self.get::<raw::Slice<()>> |s| {
self.writer.write_char('&');
self.write_vec_range(mtbl, s.data, s.len, inner);
}
fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint,
mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<u8> |b| {
+ do self.get::<()> |b| {
self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
}
}
fn visit_opaque_box(&self) -> bool {
self.writer.write_char('@');
- do self.get::<&managed::raw::BoxRepr> |b| {
+ do self.get::<&raw::Box<()>> |b| {
let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
- self.visit_ptr_inner(p, b.header.type_desc);
+ self.visit_ptr_inner(p, b.type_desc);
}
}
use libc::{c_char, c_void, size_t, STDERR_FILENO};
use io;
use io::{Writer, WriterUtil};
-use managed::raw::BoxRepr;
use option::{Option, None, Some};
use uint;
use str;
use str::{OwnedStr, StrSlice};
use sys;
+use unstable::raw;
use vec::ImmutableVector;
#[allow(non_camel_case_types)]
#[deriving(Eq)]
struct BorrowRecord {
- box: *mut BoxRepr,
+ box: *mut raw::Box<()>,
file: *c_char,
line: size_t
}
let _ = try_take_task_borrow_list();
}
-unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
+unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
debug_borrow("fail_borrowed: ", box, 0, 0, file, line);
match try_take_task_borrow_list() {
#[inline]
pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint {
- let a: *mut BoxRepr = transmute(a);
- let old_ref_count = (*a).header.ref_count;
+ let a = a as *mut raw::Box<()>;
+ let old_ref_count = (*a).ref_count;
let new_ref_count = old_ref_count | FROZEN_BIT;
debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line);
fail_borrowed(a, file, line);
}
- (*a).header.ref_count = new_ref_count;
+ (*a).ref_count = new_ref_count;
old_ref_count
}
#[inline]
pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint {
- let a: *mut BoxRepr = transmute(a);
- let old_ref_count = (*a).header.ref_count;
+ let a = a as *mut raw::Box<()>;
+ let old_ref_count = (*a).ref_count;
let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT;
debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line);
fail_borrowed(a, file, line);
}
- (*a).header.ref_count = new_ref_count;
+ (*a).ref_count = new_ref_count;
old_ref_count
}
file: *c_char, line: size_t) {
if (old_ref_count & ALL_BITS) == 0 {
// was not borrowed before
- let a: *mut BoxRepr = transmute(a);
+ let a = a as *mut raw::Box<()>;
debug_borrow("record_borrow:", a, old_ref_count, 0, file, line);
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
if (old_ref_count & ALL_BITS) == 0 {
// was not borrowed before, so we should find the record at
// the end of the list
- let a: *mut BoxRepr = transmute(a);
+ let a = a as *mut raw::Box<()>;
debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line);
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
// Sometimes the box is null, if it is conditionally frozen.
// See e.g. #4904.
if !a.is_null() {
- let a: *mut BoxRepr = transmute(a);
- let old_ref_count = (*a).header.ref_count;
+ let a = a as *mut raw::Box<()>;
+ let old_ref_count = (*a).ref_count;
let new_ref_count =
(old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS);
debug_borrow("return_to_mut:",
a, old_ref_count, new_ref_count, file, line);
- (*a).header.ref_count = new_ref_count;
+ (*a).ref_count = new_ref_count;
}
}
pub unsafe fn check_not_borrowed(a: *u8,
file: *c_char,
line: size_t) {
- let a: *mut BoxRepr = transmute(a);
- let ref_count = (*a).header.ref_count;
+ let a = a as *mut raw::Box<()>;
+ let ref_count = (*a).ref_count;
debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line);
if (ref_count & FROZEN_BIT) != 0 {
fail_borrowed(a, file, line);
// except according to those terms.
use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
-use managed::raw::{BoxHeaderRepr, BoxRepr};
use unstable::intrinsics::TyDesc;
+use unstable::raw;
use sys::size_of;
extern {
#[inline]
fn get_box_size(body_size: uint, body_align: uint) -> uint {
- let header_size = size_of::<BoxHeaderRepr>();
+ let header_size = size_of::<raw::Box<()>>();
// FIXME (#2699): This alignment calculation is suspicious. Is it right?
let total_size = align_to(header_size, body_align) + body_size;
total_size
let total_size = get_box_size(size, (*td).align);
let p = malloc_raw(total_size as uint);
- let box: *mut BoxRepr = p as *mut BoxRepr;
- (*box).header.type_desc = td;
+ let box = p as *mut raw::Box<()>;
+ (*box).type_desc = td;
box as *c_char
}
use libc;
use libc::{c_void, uintptr_t, size_t};
use ops::Drop;
-use repr::BoxRepr;
use rt;
use rt::OldTaskContext;
use rt::local::Local;
use rt::task::Task;
+use unstable::raw;
type MemoryRegion = c_void;
struct BoxedRegion {
env: *Env,
backing_region: *MemoryRegion,
- live_allocs: *BoxRepr
+ live_allocs: *raw::Box<()>,
}
pub type OpaqueBox = c_void;
}
}
-pub fn live_allocs() -> *BoxRepr {
+pub fn live_allocs() -> *raw::Box<()> {
let region = match rt::context() {
OldTaskContext => {
unsafe { rust_current_boxed_region() }
use either::{Left, Right};
use option::{Option, Some, None};
-use sys;
use cast::transmute;
use clone::Clone;
+use unstable::raw;
use super::sleeper_list::SleeperList;
use super::work_queue::WorkQueue;
// XXX: Some hacks to put a &fn in Scheduler without borrowck
// complaining
-type UnsafeTaskReceiver = sys::Closure;
+type UnsafeTaskReceiver = raw::Closure;
trait ClosureConverter {
fn from_fn(&fn(&mut Scheduler, BlockedTask)) -> Self;
fn to_fn(self) -> &fn(&mut Scheduler, BlockedTask);
impl Unwinder {
pub fn try(&mut self, f: &fn()) {
- use sys::Closure;
+ use unstable::raw::Closure;
unsafe {
let closure: Closure = transmute(f);
use ptr::RawPtr;
use to_str::ToStr;
use uint;
+use unstable::raw::Repr;
use vec;
use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
unsafe {
assert!(is_utf8(vector));
- let (ptr, len): (*u8, uint) = ::cast::transmute(vector);
- let string: &'a str = ::cast::transmute((ptr, len + 1));
- string
+ let mut s = vector.repr();
+ s.len += 1;
+ cast::transmute(s)
}
}
*/
pub fn from_byte(b: u8) -> ~str {
assert!(b < 128u8);
- unsafe { ::cast::transmute(~[b, 0u8]) }
+ unsafe { cast::transmute(~[b, 0u8]) }
}
/// Convert a char to a string
do s.as_mut_buf |buf, _| {
do sep.as_imm_buf |sepbuf, seplen| {
let seplen = seplen - 1;
- let mut buf = ::cast::transmute_mut_unsafe(buf);
+ let mut buf = cast::transmute_mut_unsafe(buf);
for self.iter().advance |ss| {
do ss.as_slice().as_imm_buf |ssbuf, sslen| {
let sslen = sslen - 1;
use cast;
use libc;
use ptr;
- use str::raw;
- use str::{is_utf8};
+ use str::is_utf8;
use vec;
use vec::MutableVector;
+ use unstable::raw::{Slice, String};
/// Create a Rust string from a null-terminated *u8 buffer
pub unsafe fn from_buf(buf: *u8) -> ~str {
v.push(0u8);
assert!(is_utf8(v));
- return ::cast::transmute(v);
+ return cast::transmute(v);
}
/// Create a Rust string from a null-terminated C string
pub unsafe fn from_c_str(c_str: *libc::c_char) -> ~str {
- from_buf(::cast::transmute(c_str))
+ from_buf(c_str as *u8)
}
/// Create a Rust string from a `*c_char` buffer of the given length
pub unsafe fn from_c_str_len(c_str: *libc::c_char, len: uint) -> ~str {
- from_buf_len(::cast::transmute(c_str), len)
+ from_buf_len(c_str as *u8, len)
}
/// Converts a vector of bytes to a new owned string.
}
/// Converts a byte to a string.
- pub unsafe fn from_byte(u: u8) -> ~str { raw::from_bytes([u]) }
+ pub unsafe fn from_byte(u: u8) -> ~str { from_bytes([u]) }
/// Form a slice from a C string. Unsafe because the caller must ensure the
/// C string has the static lifetime, or else the return value may be
len += 1u;
curr = ptr::offset(s, len);
}
- let v = (s, len + 1);
- assert!(is_utf8(::cast::transmute(v)));
- ::cast::transmute(v)
+ let v = Slice { data: s, len: len + 1 };
+ assert!(is_utf8(cast::transmute(v)));
+ cast::transmute(v)
}
/**
assert!((begin <= end));
assert!((end <= n));
- let tuple = (ptr::offset(sbuf, begin), end - begin + 1);
- ::cast::transmute(tuple)
+ cast::transmute(Slice {
+ data: ptr::offset(sbuf, begin),
+ len: end - begin + 1,
+ })
}
}
/// Sets the length of the string and adds the null terminator
#[inline]
pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
- let v: **mut vec::UnboxedVecRepr = cast::transmute(v);
- let repr: *mut vec::UnboxedVecRepr = *v;
+ let v: **mut String = cast::transmute(v);
+ let repr = *v;
(*repr).fill = new_len + 1u;
- let null = ptr::mut_offset(cast::transmute(&((*repr).data)),
- new_len);
+ let null = ptr::mut_offset(&mut ((*repr).data), new_len);
*null = 0u8;
}
let v = at_vec::from_fn(self.len() + 1, |i| {
if i == self.len() { 0 } else { self[i] }
});
- unsafe { ::cast::transmute(v) }
+ unsafe { cast::transmute(v) }
}
/// Converts to a vector of `u16` encoded as UTF-16.
*/
fn as_bytes(&self) -> &'self [u8] {
unsafe {
- let (ptr, len): (*u8, uint) = ::cast::transmute(*self);
- let outgoing_tuple: (*u8, uint) = (ptr, len - 1);
- ::cast::transmute(outgoing_tuple)
+ let mut slice = self.repr();
+ slice.len -= 1;
+ cast::transmute(slice)
}
}
*/
#[inline]
fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
- let ptr: &'a ~[u8] = unsafe { ::cast::transmute(self) };
+ let ptr: &'a ~[u8] = unsafe { cast::transmute(self) };
let slice: &'a [u8] = *ptr;
slice
}
*/
#[inline]
fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
- let ptr: &'a @[u8] = unsafe { ::cast::transmute(self) };
+ let ptr: &'a @[u8] = unsafe { cast::transmute(self) };
let slice: &'a [u8] = *ptr;
slice
}
do self.as_imm_buf |lbuf, _llen| {
do rhs.as_imm_buf |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
- let dst = ::cast::transmute_mut_unsafe(dst);
+ let dst = cast::transmute_mut_unsafe(dst);
ptr::copy_memory(dst, rbuf, rlen);
}
}
do self.as_imm_buf |lbuf, _llen| {
do rhs.as_imm_buf |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
- let dst = ::cast::transmute_mut_unsafe(dst);
+ let dst = cast::transmute_mut_unsafe(dst);
ptr::copy_memory(dst, rbuf, rlen);
}
}
/// string, and includes the null terminator.
#[inline]
fn to_bytes_with_null(self) -> ~[u8] {
- unsafe { ::cast::transmute(self) }
+ unsafe { cast::transmute(self) }
}
#[inline]
use str;
use unstable::intrinsics;
-/// The representation of a Rust closure
-pub struct Closure {
- code: *(),
- env: *(),
-}
-
pub mod rustrt {
use libc::{c_char, size_t};
#[test]
fn synthesize_closure() {
+ use unstable::raw::Closure;
unsafe {
let x = 10;
let f: &fn(int) -> int = |y| x + y;
use local_data;
use prelude::*;
use ptr;
-use sys;
use task::rt;
+use unstable::raw;
use util;
use super::rt::rust_task;
}
unsafe fn key_to_key_value<T: 'static>(key: local_data::Key<T>) -> *libc::c_void {
- let pair: sys::Closure = cast::transmute_copy(&key);
+ let pair: raw::Closure = cast::transmute_copy(&key);
return pair.code as *libc::c_void;
}
pub mod lang;
pub mod sync;
pub mod atomics;
+pub mod raw;
/**
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cast;
+use unstable::intrinsics::TyDesc;
+
+/// The representation of a Rust managed box
+pub struct Box<T> {
+ ref_count: uint,
+ type_desc: *TyDesc,
+ prev: *Box<T>,
+ next: *Box<T>,
+ data: T
+}
+
+/// The representation of a Rust vector
+pub struct Vec<T> {
+ fill: uint,
+ alloc: uint,
+ data: T
+}
+
+/// The representation of a Rust string
+pub type String = Vec<u8>;
+
+/// The representation of a Rust slice
+pub struct Slice<T> {
+ data: *T,
+ len: uint
+}
+
+/// The representation of a Rust closure
+pub struct Closure {
+ code: *(),
+ env: *(),
+}
+
+/// This trait is meant to map equivalences between raw structs and their
+/// corresponding rust values.
+pub trait Repr<T> {
+ /// This function "unwraps" a rust value (without consuming it) into its raw
+ /// struct representation. This can be used to read/write different values
+ /// for the struct. This is a safe method because by default it does not
+ /// give write-access to the struct returned.
+ fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } }
+}
+
+impl<'self, T> Repr<Slice<T>> for &'self [T] {}
+impl<'self> Repr<Slice<u8>> for &'self str {}
+impl<T> Repr<*Box<T>> for @T {}
+impl<T> Repr<*Box<Vec<T>>> for @[T] {}
+
+// sure would be nice to have this
+// impl<T> Repr<*Vec<T>> for ~[T] {}
#[warn(non_camel_case_types)];
-use cast::transmute;
use cast;
use clone::Clone;
use container::{Container, Mutable};
use uint;
use unstable::intrinsics;
use unstable::intrinsics::{get_tydesc, contains_managed};
+use unstable::raw::{Box, Repr, Slice, Vec};
use vec;
use util;
vec
} else {
let alloc = capacity * sys::nonzero_size_of::<T>();
- let ptr = malloc_raw(alloc + sys::size_of::<UnboxedVecRepr>()) as *mut UnboxedVecRepr;
+ let ptr = malloc_raw(alloc + sys::size_of::<Vec<()>>()) as *mut Vec<()>;
(*ptr).alloc = alloc;
(*ptr).fill = 0;
cast::transmute(ptr)
assert!(end <= self.len());
do self.as_imm_buf |p, _len| {
unsafe {
- transmute((ptr::offset(p, start),
- (end - start) * sys::nonzero_size_of::<T>()))
+ cast::transmute(Slice {
+ data: ptr::offset(p, start),
+ len: (end - start) * sys::nonzero_size_of::<T>(),
+ })
}
}
}
unsafe {
let p = vec::raw::to_ptr(self);
VecIterator{ptr: p,
- end: cast::transmute(p as uint + self.len() *
- sys::nonzero_size_of::<T>()),
+ end: (p as uint + self.len() *
+ sys::nonzero_size_of::<T>()) as *T,
lifetime: cast::transmute(p)}
}
}
/// bounds checking.
#[inline]
unsafe fn unsafe_ref(&self, index: uint) -> *T {
- let (ptr, _): (*T, uint) = transmute(*self);
- ptr.offset(index)
+ self.repr().data.offset(index)
}
/**
// into `s` and pass them to `f()`, but in fact they are potentially
// pointing at *mutable memory*. Use `as_mut_buf` instead!
- unsafe {
- let v : *(*T,uint) = transmute(self);
- let (buf,len) = *v;
- f(buf, len / sys::nonzero_size_of::<T>())
- }
+ let s = self.repr();
+ f(s.data, s.len / sys::nonzero_size_of::<T>())
}
}
unsafe {
let td = get_tydesc::<T>();
if contains_managed::<T>() {
- let ptr: *mut *mut raw::VecRepr = cast::transmute(self);
+ let ptr: *mut *mut Box<Vec<()>> = cast::transmute(self);
::at_vec::raw::reserve_raw(td, ptr, n);
} else {
- let ptr: *mut *mut UnboxedVecRepr = cast::transmute(self);
+ let ptr: *mut *mut Vec<()> = cast::transmute(self);
let alloc = n * sys::nonzero_size_of::<T>();
- let size = alloc + sys::size_of::<UnboxedVecRepr>();
+ let size = alloc + sys::size_of::<Vec<()>>();
if alloc / sys::nonzero_size_of::<T>() != n || size < alloc {
fail!("vector size is too large: %u", n);
}
*ptr = realloc_raw(*ptr as *mut c_void, size)
- as *mut UnboxedVecRepr;
+ as *mut Vec<()>;
(**ptr).alloc = alloc;
}
}
fn capacity(&self) -> uint {
unsafe {
if contains_managed::<T>() {
- let repr: **raw::VecRepr = transmute(self);
- (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
+ let repr: **Box<Vec<()>> = cast::transmute(self);
+ (**repr).data.alloc / sys::nonzero_size_of::<T>()
} else {
- let repr: **UnboxedVecRepr = transmute(self);
+ let repr: **Vec<()> = cast::transmute(self);
(**repr).alloc / sys::nonzero_size_of::<T>()
}
}
fn push(&mut self, t: T) {
unsafe {
if contains_managed::<T>() {
- let repr: **raw::VecRepr = transmute(&mut *self);
- let fill = (**repr).unboxed.fill;
- if (**repr).unboxed.alloc <= fill {
+ let repr: **Box<Vec<()>> = cast::transmute(&mut *self);
+ let fill = (**repr).data.fill;
+ if (**repr).data.alloc <= fill {
let new_len = self.len() + 1;
self.reserve_at_least(new_len);
}
self.push_fast(t);
} else {
- let repr: **UnboxedVecRepr = transmute(&mut *self);
+ let repr: **Vec<()> = cast::transmute(&mut *self);
let fill = (**repr).fill;
if (**repr).alloc <= fill {
let new_len = self.len() + 1;
#[inline] // really pretty please
unsafe fn push_fast(&mut self, t: T) {
if contains_managed::<T>() {
- let repr: **mut raw::VecRepr = transmute(self);
- let fill = (**repr).unboxed.fill;
- (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
- let p = to_unsafe_ptr(&((**repr).unboxed.data));
+ let repr: **mut Box<Vec<u8>> = cast::transmute(self);
+ let fill = (**repr).data.fill;
+ (**repr).data.fill += sys::nonzero_size_of::<T>();
+ let p = to_unsafe_ptr(&((**repr).data.data));
let p = ptr::offset(p, fill) as *mut T;
intrinsics::move_val_init(&mut(*p), t);
} else {
- let repr: **mut UnboxedVecRepr = transmute(self);
+ let repr: **mut Vec<u8> = cast::transmute(self);
let fill = (**repr).fill;
(**repr).fill += sys::nonzero_size_of::<T>();
let p = to_unsafe_ptr(&((**repr).data));
{
let first_slice = self.slice(0, 1);
let last_slice = self.slice(next_ln, ln);
- raw::copy_memory(transmute(last_slice), first_slice, 1);
+ raw::copy_memory(cast::transmute(last_slice), first_slice, 1);
}
// Memcopy everything to the left one element
{
let init_slice = self.slice(0, next_ln);
let tail_slice = self.slice(1, ln);
- raw::copy_memory(transmute(init_slice),
+ raw::copy_memory(cast::transmute(init_slice),
tail_slice,
next_ln);
}
*/
fn move_from(self, src: ~[T], start: uint, end: uint) -> uint;
- unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
- unsafe fn unsafe_set(&self, index: uint, val: T);
+ unsafe fn unsafe_mut_ref(self, index: uint) -> *mut T;
+ unsafe fn unsafe_set(self, index: uint, val: T);
fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U;
}
assert!(end <= self.len());
do self.as_mut_buf |p, _len| {
unsafe {
- transmute((ptr::mut_offset(p, start),
- (end - start) * sys::nonzero_size_of::<T>()))
+ cast::transmute(Slice {
+ data: ptr::mut_offset(p, start) as *T,
+ len: (end - start) * sys::nonzero_size_of::<T>()
+ })
}
}
}
unsafe {
let p = vec::raw::to_mut_ptr(self);
VecMutIterator{ptr: p,
- end: cast::transmute(p as uint + self.len() *
- sys::nonzero_size_of::<T>()),
+ end: (p as uint + self.len() *
+ sys::nonzero_size_of::<T>()) as *mut T,
lifetime: cast::transmute(p)}
}
}
}
#[inline]
- unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T {
- let pair_ptr: &(*mut T, uint) = transmute(self);
- let (ptr, _) = *pair_ptr;
- ptr.offset(index)
+ unsafe fn unsafe_mut_ref(self, index: uint) -> *mut T {
+ ptr::mut_offset(self.repr().data as *mut T, index)
}
#[inline]
- unsafe fn unsafe_set(&self, index: uint, val: T) {
+ unsafe fn unsafe_set(self, index: uint, val: T) {
*self.unsafe_mut_ref(index) = val;
}
/// Similar to `as_imm_buf` but passing a `*mut T`
#[inline]
fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U {
- let (buf, len): (*mut T, uint) = unsafe { transmute(self) };
- f(buf, len / sys::nonzero_size_of::<T>())
+ let Slice{ data, len } = self.repr();
+ f(data as *mut T, len / sys::nonzero_size_of::<T>())
}
}
raw::from_buf_raw(ptr, elts)
}
-/// The internal 'unboxed' representation of a vector
-#[allow(missing_doc)]
-pub struct UnboxedVecRepr {
- fill: uint,
- alloc: uint,
- data: u8
-}
-
/// Unsafe operations
pub mod raw {
- use cast::transmute;
+ use cast;
use clone::Clone;
- use managed;
use option::Some;
use ptr;
use sys;
use unstable::intrinsics;
- use vec::{UnboxedVecRepr, with_capacity, ImmutableVector, MutableVector};
+ use vec::{with_capacity, ImmutableVector, MutableVector};
use unstable::intrinsics::contains_managed;
-
- /// The internal representation of a (boxed) vector
- #[allow(missing_doc)]
- pub struct VecRepr {
- box_header: managed::raw::BoxHeaderRepr,
- unboxed: UnboxedVecRepr
- }
-
- /// The internal representation of a slice
- pub struct SliceRepr {
- /// Pointer to the base of this slice
- data: *u8,
- /// The length of the slice
- len: uint
- }
+ use unstable::raw::{Box, Vec, Slice};
/**
* Sets the length of a vector
#[inline]
pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
if contains_managed::<T>() {
- let repr: **mut VecRepr = transmute(v);
- (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
+ let repr: **mut Box<Vec<()>> = cast::transmute(v);
+ (**repr).data.fill = new_len * sys::nonzero_size_of::<T>();
} else {
- let repr: **mut UnboxedVecRepr = transmute(v);
+ let repr: **mut Vec<()> = cast::transmute(v);
(**repr).fill = new_len * sys::nonzero_size_of::<T>();
}
}
*/
#[inline]
pub fn to_ptr<T>(v: &[T]) -> *T {
- unsafe {
- let repr: **SliceRepr = transmute(&v);
- transmute(&((**repr).data))
- }
+ v.repr().data
}
/** see `to_ptr()` */
#[inline]
pub fn to_mut_ptr<T>(v: &mut [T]) -> *mut T {
- unsafe {
- let repr: **SliceRepr = transmute(&v);
- transmute(&((**repr).data))
- }
+ v.repr().data as *mut T
}
/**
pub unsafe fn buf_as_slice<T,U>(p: *T,
len: uint,
f: &fn(v: &[T]) -> U) -> U {
- let pair = (p, len * sys::nonzero_size_of::<T>());
- let v : *(&'blk [T]) = transmute(&pair);
- f(*v)
+ f(cast::transmute(Slice {
+ data: p,
+ len: len * sys::nonzero_size_of::<T>()
+ }))
}
/**
pub unsafe fn mut_buf_as_slice<T,U>(p: *mut T,
len: uint,
f: &fn(v: &mut [T]) -> U) -> U {
- let pair = (p, len * sys::nonzero_size_of::<T>());
- let v : *(&'blk mut [T]) = transmute(&pair);
- f(*v)
+ f(cast::transmute(Slice {
+ data: p as *T,
+ len: len * sys::nonzero_size_of::<T>()
+ }))
}
/**
use std::libc::c_void;
use std::ptr;
use std::sys;
-use std::vec::UnboxedVecRepr;
use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
+use std::unstable::raw::Vec;
#[doc = "High-level interfaces to `std::unstable::intrinsics::visit_ty` reflection system."]
}
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
- self.align_to::<UnboxedVecRepr>();
+ self.align_to::<Vec<()>>();
// FIXME (#3732): Inner really has to move its own pointers on this one.
// or else possibly we could have some weird interface wherein we
// read-off a word from inner's pointers, but the read-word has to