From e0d43b023ed219d47c0785f10c62a62350aa4ea1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 23:19:52 -0700 Subject: [PATCH] core: Implement necessary traits for ~[T]/~str Coherence requires that libcore's traits be implemented in libcore for ~[T] and ~str (due to them being language defined types). These implementations cannot live in libcore forever, but for now, until Heap/Box/Uniq is a lang item, these implementations must reside inside of libcore. While not perfect implementations, these shouldn't reside in libcore for too long. With some form of lang item these implementations can be in a proper crate because the lang item will not be present in libcore. --- src/libcore/lib.rs | 3 + src/libcore/should_not_exist.rs | 197 ++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 src/libcore/should_not_exist.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index e89f5181402..a1833534ab8 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -73,3 +73,6 @@ pub mod char; pub mod slice; pub mod str; pub mod tuple; + +// FIXME: this module should not exist +mod should_not_exist; diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs new file mode 100644 index 00000000000..83e4c0d339f --- /dev/null +++ b/src/libcore/should_not_exist.rs @@ -0,0 +1,197 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cast; +use char::Char; +use clone::Clone; +use container::Container; +use default::Default; +use intrinsics; +use iter::{Iterator, FromIterator}; +use mem; +use num::{CheckedMul, CheckedAdd}; +use ops::Add; +use option::{Some, None}; +use ptr::RawPtr; +use ptr; +use raw::Vec; +use slice::{ImmutableVector, Vector}; +use str::StrSlice; + +#[allow(ctypes)] +extern { + fn malloc(size: uint) -> *u8; + fn free(ptr: *u8); +} + +unsafe fn alloc(cap: uint) -> *mut Vec<()> { + let cap = cap.checked_add(&mem::size_of::>()).expect("cap overflow"); + let ret = malloc(cap) as *mut Vec<()>; + if ret.is_null() { + intrinsics::abort(); + } + (*ret).fill = 0; + (*ret).alloc = cap; + ret +} + +// Strings + +impl Default for ~str { + fn default() -> ~str { + unsafe { + // Get some memory + let ptr = alloc(0); + + // Initialize the memory + (*ptr).fill = 0; + (*ptr).alloc = 0; + + cast::transmute(ptr) + } + } +} + +impl Clone for ~str { + fn clone(&self) -> ~str { + // Don't use the clone() implementation above because it'll start + // requiring the eh_personality lang item (no fun) + unsafe { + let bytes = self.as_bytes().as_ptr(); + let len = self.len(); + + let ptr = alloc(len) as *mut Vec; + ptr::copy_nonoverlapping_memory(&mut (*ptr).data, bytes, len); + (*ptr).fill = len; + (*ptr).alloc = len; + + cast::transmute(ptr) + } + } +} + +impl FromIterator for ~str { + #[inline] + fn from_iter>(mut iterator: T) -> ~str { + let (lower, _) = iterator.size_hint(); + let mut cap = if lower == 0 {16} else {lower}; + let mut len = 0; + let mut tmp = [0u8, ..4]; + + unsafe { + let mut ptr = alloc(cap) as *mut Vec; + let mut ret = cast::transmute(ptr); + for ch in iterator { + let amt = ch.encode_utf8(tmp); + + if len + amt > cap { + cap = cap.checked_mul(&2).expect("cap overflow"); + if cap < len + amt { + cap = len + amt; + } + let ptr2 = alloc(cap) as *mut Vec; + ptr::copy_nonoverlapping_memory(&mut (*ptr2).data, + &(*ptr).data, + len); + free(ptr as *u8); + cast::forget(ret); + ret = cast::transmute(ptr2); + ptr = ptr2; + } + + let base = &mut (*ptr).data as *mut u8; + for byte in tmp.slice_to(amt).iter() { + *base.offset(len as int) = *byte; + len += 1; + } + (*ptr).fill = len; + } + ret + } + } +} + +impl<'a> Add<&'a str,~str> for &'a str { + #[inline] + fn add(&self, rhs: & &'a str) -> ~str { + let amt = self.len().checked_add(&rhs.len()).expect("len overflow"); + unsafe { + let ptr = alloc(amt) as *mut Vec; + let base = &mut (*ptr).data as *mut _; + ptr::copy_nonoverlapping_memory(base, + self.as_bytes().as_ptr(), + self.len()); + let base = base.offset(self.len() as int); + ptr::copy_nonoverlapping_memory(base, + rhs.as_bytes().as_ptr(), + rhs.len()); + (*ptr).fill = amt; + (*ptr).alloc = amt; + cast::transmute(ptr) + } + } +} + +// Arrays + +impl Clone for ~[A] { + #[inline] + fn clone(&self) -> ~[A] { + self.iter().map(|a| a.clone()).collect() + } +} + +impl FromIterator for ~[A] { + fn from_iter>(mut iterator: T) -> ~[A] { + let (lower, _) = iterator.size_hint(); + let cap = if lower == 0 {16} else {lower}; + let mut cap = cap.checked_mul(&mem::size_of::()).expect("cap overflow"); + let mut len = 0; + + unsafe { + let mut ptr = alloc(cap) as *mut Vec; + let mut ret = cast::transmute(ptr); + for elt in iterator { + if len * mem::size_of::() >= cap { + cap = cap.checked_mul(&2).expect("cap overflow"); + let ptr2 = alloc(cap) as *mut Vec; + ptr::copy_nonoverlapping_memory(&mut (*ptr2).data, + &(*ptr).data, + len); + free(ptr as *u8); + cast::forget(ret); + ret = cast::transmute(ptr2); + ptr = ptr2; + } + + let base = &mut (*ptr).data as *mut A; + intrinsics::move_val_init(&mut *base.offset(len as int), elt); + len += 1; + (*ptr).fill = len * mem::nonzero_size_of::(); + } + ret + } + } +} + +impl<'a,T:Clone, V: Vector> Add for &'a [T] { + #[inline] + fn add(&self, rhs: &V) -> ~[T] { + let first = self.iter().map(|t| t.clone()); + first.chain(rhs.as_slice().iter().map(|t| t.clone())).collect() + } +} + +impl> Add for ~[T] { + #[inline] + fn add(&self, rhs: &V) -> ~[T] { + self.as_slice() + rhs.as_slice() + } +}