From 091ce53368bf06417fe2fa6b995195675eaeb4c8 Mon Sep 17 00:00:00 2001 From: missing Date: Mon, 16 May 2022 09:42:00 -0500 Subject: [PATCH] vec![v; n] and clippy warnings --- src/impls.rs | 8 ++++++ src/iter.rs | 5 +++- src/lib.rs | 69 ++++++++++++++++++++++++++++++++++------------------ src/test.rs | 10 ++++++++ 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/impls.rs b/src/impls.rs index d99a756..1a171c2 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -1,9 +1,17 @@ //! Implements `Debug`, and `PartialEq` for various list-like types. +#[allow(clippy::wildcard_imports)] use super::*; use std::fmt::Debug; +impl Default for Vec { + fn default() -> Self { + Self::new() + } +} + + impl Debug for Vec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_list().entries(self.iter()).finish() diff --git a/src/iter.rs b/src/iter.rs index 934f50d..01c89b4 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,5 +1,6 @@ //! Iteration. +#[allow(clippy::wildcard_imports)] use super::*; struct BaseIter { @@ -93,6 +94,7 @@ impl<'a, T: ?Sized> IntoIterator for &'a mut Vec { } /// A by-mut iterator over the elements of a [`Vec`]. +#[allow(clippy::module_name_repetitions)] pub struct IterMut<'a, T: ?Sized> { base: BaseIter, _phantom: PhantomData<&'a mut T> @@ -132,6 +134,7 @@ impl IntoIterator for Vec { } /// A by-value iterator over the elements of a [`Vec`]. +#[allow(clippy::module_name_repetitions)] pub struct IntoIter { ptr: NonNull, capacity: usize, @@ -205,7 +208,7 @@ impl FromIterator for Vec { fn from_iter>(iter: I) -> Self { let mut vec = Vec::new(); - for item in iter.into_iter() { + for item in iter { vec.push(item); } diff --git a/src/lib.rs b/src/lib.rs index 9d4e829..1075f15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,6 +95,8 @@ #![feature(coerce_unsized)] #![warn(missing_docs)] +#![warn(clippy::pedantic)] +#![allow(clippy::must_use_candidate)] #[cfg(test)] mod test; @@ -171,16 +173,31 @@ impl Vec { } } - /// Creates a new vector with the given capacity, measured in bytes. - pub fn with_capacity_bytes(cap: usize) -> Self { - let ptr = NonNull::new(unsafe { alloc(Layout::from_size_align(cap, 8).unwrap().pad_to_align()) }).unwrap(); - Self { - ptr, - len: 0, - capacity: cap, - end_ptr: ptr, - _phantom: PhantomData + /// Creates a new vector that holds `len` copies of `v`. + /// + /// Only avaliable when `T: Sized`. + pub fn from_elem(v: T, len: usize) -> Self where T: Sized + Clone { + let mut vec = Self::with_capacity(len); + + for _ in 0..len { + vec.push(v.clone()); } + + vec + } + + /// Creates a new vector that can hold the given amount of `T`s. + /// + /// Only avaliable when `T: Sized`. + pub fn with_capacity(cap: usize) -> Self where T: Sized { + Self::with_capacity_for::(cap) + } + + /// Creates a new vector with the given capacity, measured in bytes.\ + pub fn with_capacity_bytes(cap: usize) -> Self { + let mut vec = Self::new(); + unsafe { vec.realloc(cap); } + vec } /// Creates a new vector with enough capacity to hold the given amount of `U`s. @@ -287,7 +304,7 @@ impl Vec { let size = size_of_val(v); ptr = align_up_mut(ptr, align_of_val(v)); - memcpy(v as *const _ as _, ptr, size); + memcpy((v as *const T).cast(), ptr, size); let meta = self.get_ptr(i).to_raw_parts().1; self.set_extra_from_ptr(i, ptr::from_raw_parts(ptr.cast(), meta)); ptr = ptr.wrapping_add(size); @@ -344,6 +361,8 @@ impl Vec { /// Gets a reference to the element at the specified index. /// + /// # Safety + /// /// Immediate UB if the index is out-of-bounds. pub unsafe fn get_unchecked(&self, index: usize) -> &T { &*self.get_ptr(index) @@ -362,6 +381,8 @@ impl Vec { /// Gets a mutable reference to the element at the specified index. /// + /// # Safety + /// /// Immediate UB if the index is out-of-bounds. pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { &mut *(self.get_ptr(index) as *mut _) @@ -372,6 +393,11 @@ impl Vec { self.len } + /// Returns `true` if the vector holds no elements. + pub fn is_empty(&self) -> bool { + self.len == 0 + } + /// Returns the capacity, which is the size of the allocation in bytes. pub fn capacity(&self) -> usize { self.capacity @@ -448,13 +474,16 @@ impl Vec<[T]> { /// /// Only avaliable for `Vec<[T]>`. pub fn as_slice_flatten(&self) -> &[T] { - assert!(self.len > 0); + if self.len == 0 { + return unsafe { slice::from_raw_parts(NonNull::dangling().as_ptr(), 0) } + } // SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked` unsafe { - slice::from_raw_parts(self.get_ptr(0).to_raw_parts().0 as _, { + slice::from_raw_parts(self.get_ptr(0).to_raw_parts().0.cast(), { let start = self.get_ptr(0).to_raw_parts().0 as usize; let end = self.end_ptr.as_ptr() as usize; + debug_assert_eq!((end - start) % size_of::(), 0); (end - start) / size_of::() // integer division! }) } @@ -464,13 +493,16 @@ impl Vec<[T]> { /// /// Only avaliable for `Vec<[T]>`. pub fn as_mut_slice_flatten(&mut self) -> &mut [T] { - assert!(self.len > 0); + if self.len == 0 { + return unsafe { slice::from_raw_parts_mut(NonNull::dangling().as_ptr(), 0) } + } // SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked` unsafe { slice::from_raw_parts_mut(self.get_ptr(0).to_raw_parts().0 as _, { let start = self.get_ptr(0).to_raw_parts().0 as usize; let end = self.end_ptr.as_ptr() as usize; + debug_assert_eq!((end - start) % size_of::(), 0); (end - start) / size_of::() // integer division! }) } @@ -507,15 +539,6 @@ impl Vec { } } -impl Vec { - /// Creates a new vector that can hold the given amount of `T`s. - /// - /// Only avaliable when `T: Sized`. - pub fn with_capacity(cap: usize) -> Self { - Self::with_capacity_for::(cap) - } -} - impl Drop for Vec { fn drop(&mut self) { unsafe { @@ -582,7 +605,7 @@ macro_rules! vec { vec }}; ($elem:expr; $n:expr) => { - compile_error!("dyn_vec::vec![T; N] is currently not supported"); + $crate::Vec::from_elem($elem, $n) }; ($($elem:expr),+ $(,)?) => {{ let mut vec = $crate::Vec::new(); diff --git a/src/test.rs b/src/test.rs index 0b5cc28..ece4a5d 100644 --- a/src/test.rs +++ b/src/test.rs @@ -50,6 +50,9 @@ fn all_macro() { ]; let vec3: Vec = vec![unsized: 1, String::from("foo"), true]; assert_eq!(vec2.debug(), vec3.debug()); + + let vec4: Vec = vec![3; 5]; + assert_eq!(vec4, [3; 5]); } #[test] @@ -177,4 +180,11 @@ fn with_capacity() { vec.push(4); assert_eq!(prev_ptr, vec.as_ptr()); + + vec.push(5); + vec.push(6); + vec.push(7); + // should have realloc'ed by now + + assert_ne!(prev_ptr, vec.as_ptr()); } \ No newline at end of file