use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::mem::ManuallyDrop;
use core::ops::{Deref, DerefMut};
use core::ptr;
use core::slice;
use crate::de::{DecodeBytes, UnsizedVisitor};
use crate::{Context, Decoder};
use super::{Alloc, AllocError, Allocator, GlobalAllocator};
pub struct Vec<T, A>
where
A: Allocator,
{
buf: A::Alloc<T>,
len: usize,
}
impl<T, A> Vec<T, A>
where
A: Allocator,
{
#[inline]
pub fn new_in(alloc: A) -> Self {
Self {
buf: alloc.alloc_empty::<T>(),
len: 0,
}
}
#[cfg(feature = "alloc")]
pub fn into_std(self) -> Result<rust_alloc::vec::Vec<T>, Self> {
if !A::IS_GLOBAL {
return Err(self);
}
let mut this = ManuallyDrop::new(self);
unsafe {
let ptr = this.buf.as_mut_ptr();
let cap = this.buf.capacity();
Ok(rust_alloc::vec::Vec::from_raw_parts(ptr, this.len, cap))
}
}
#[inline]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Result<Self, AllocError> {
let mut buf = alloc.alloc_empty::<T>();
buf.resize(0, capacity)?;
Ok(Self { buf, len: 0 })
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn capacity(&self) -> usize {
self.buf.capacity()
}
pub fn reserve(&mut self, additional: usize) -> Result<(), AllocError> {
if size_of::<T>() != 0 {
self.buf.resize(self.len, additional)?;
}
Ok(())
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn push(&mut self, item: T) -> Result<(), AllocError> {
if size_of::<T>() != 0 {
self.buf.resize(self.len, 1)?;
unsafe {
self.buf.as_mut_ptr().add(self.len).write(item);
}
}
self.len += 1;
Ok(())
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
self.len -= 1;
unsafe { Some(ptr::read(self.buf.as_ptr().add(self.len))) }
}
#[inline]
pub fn clear(&mut self) {
unsafe { ptr::drop_in_place(slice::from_raw_parts_mut(self.buf.as_mut_ptr(), self.len)) }
self.len = 0;
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.buf.as_ptr(), self.len) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.buf.as_mut_ptr(), self.len) }
}
#[inline]
pub fn into_raw_parts(self) -> (A::Alloc<T>, usize) {
let this = ManuallyDrop::new(self);
unsafe {
let buf = ptr::addr_of!(this.buf).read();
(buf, this.len)
}
}
#[inline]
pub fn from_raw_parts(buf: A::Alloc<T>, len: usize) -> Self {
Self { buf, len }
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.capacity());
self.len = new_len;
}
pub const fn raw(&self) -> &A::Alloc<T> {
&self.buf
}
}
impl<T, A> Clone for Vec<T, A>
where
T: Clone,
A: GlobalAllocator,
{
#[inline]
fn clone(&self) -> Self {
let mut this = Self {
buf: <A as GlobalAllocator>::clone_alloc(&self.buf),
len: 0,
};
let mut b = this.buf.as_mut_ptr();
for item in self.as_slice() {
unsafe {
b.write(item.clone());
b = b.add(1);
this.len += 1;
}
}
this
}
}
impl<T, A> Vec<T, A>
where
A: Allocator,
T: Copy,
{
#[inline]
pub fn extend_from_slice(&mut self, items: &[T]) -> Result<(), AllocError> {
if size_of::<T>() != 0 {
self.buf.resize(self.len, items.len())?;
unsafe {
self.buf
.as_mut_ptr()
.add(self.len)
.copy_from_nonoverlapping(items.as_ptr(), items.len());
}
}
self.len += items.len();
Ok(())
}
#[inline]
pub fn extend(&mut self, other: Vec<T, A>) -> Result<(), AllocError> {
let (other, other_len) = other.into_raw_parts();
if let Err(buf) = self.buf.try_merge(self.len, other, other_len) {
let other = Vec::<T, A>::from_raw_parts(buf, other_len);
return self.extend_from_slice(other.as_slice());
}
self.len += other_len;
Ok(())
}
}
impl<A> fmt::Write for Vec<u8, A>
where
A: Allocator,
{
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.extend_from_slice(s.as_bytes()).map_err(|_| fmt::Error)
}
}
impl<T, A> Deref for Vec<T, A>
where
A: Allocator,
{
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, A> DerefMut for Vec<T, A>
where
A: Allocator,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl<T, A> fmt::Debug for Vec<T, A>
where
T: fmt::Debug,
A: Allocator,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.as_slice()).finish()
}
}
impl<T, A> Drop for Vec<T, A>
where
A: Allocator,
{
fn drop(&mut self) {
self.clear();
}
}
impl<T, A> AsRef<[T]> for Vec<T, A>
where
A: Allocator,
{
#[inline]
fn as_ref(&self) -> &[T] {
self
}
}
impl<T, A> AsMut<[T]> for Vec<T, A>
where
A: Allocator,
{
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self
}
}
macro_rules! impl_eq {
($lhs:ty, $rhs: ty) => {
#[allow(unused_lifetimes)]
impl<'a, 'b, T, A> PartialEq<$rhs> for $lhs
where
T: PartialEq,
A: Allocator,
{
#[inline]
fn eq(&self, other: &$rhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &$rhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
#[allow(unused_lifetimes)]
impl<'a, 'b, T, A> PartialEq<$lhs> for $rhs
where
T: PartialEq,
A: Allocator,
{
#[inline]
fn eq(&self, other: &$lhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &$lhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
};
}
macro_rules! impl_eq_array {
($lhs:ty, $rhs: ty) => {
#[allow(unused_lifetimes)]
impl<'a, 'b, T, A, const N: usize> PartialEq<$rhs> for $lhs
where
T: PartialEq,
A: Allocator,
{
#[inline]
fn eq(&self, other: &$rhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &$rhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
#[allow(unused_lifetimes)]
impl<'a, 'b, T, A, const N: usize> PartialEq<$lhs> for $rhs
where
T: PartialEq,
A: Allocator,
{
#[inline]
fn eq(&self, other: &$lhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &$lhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
};
}
impl_eq! { Vec<T, A>, [T] }
impl_eq! { Vec<T, A>, &'a [T] }
impl_eq_array! { Vec<T, A>, [T; N] }
impl_eq_array! { Vec<T, A>, &'a [T; N] }
impl<T, A, B> PartialEq<Vec<T, B>> for Vec<T, A>
where
T: PartialEq,
A: Allocator,
B: Allocator,
{
#[inline]
fn eq(&self, other: &Vec<T, B>) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl<T, A> Eq for Vec<T, A>
where
T: Eq,
A: Allocator,
{
}
impl<T, A, B> PartialOrd<Vec<T, B>> for Vec<T, A>
where
T: PartialOrd,
A: Allocator,
B: Allocator,
{
#[inline]
fn partial_cmp(&self, other: &Vec<T, B>) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<T, A> Ord for Vec<T, A>
where
T: Ord,
A: Allocator,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T, A> Borrow<[T]> for Vec<T, A>
where
A: Allocator,
{
#[inline]
fn borrow(&self) -> &[T] {
self
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<T, A> From<rust_alloc::vec::Vec<T>> for Vec<T, A>
where
A: GlobalAllocator,
{
#[inline]
fn from(value: rust_alloc::vec::Vec<T>) -> Self {
use core::ptr::NonNull;
unsafe {
let mut value = ManuallyDrop::new(value);
let ptr = NonNull::new_unchecked(value.as_mut_ptr());
let len = value.len();
let cap = value.capacity();
let buf = A::slice_from_raw_parts(ptr, cap);
Vec::from_raw_parts(buf, len)
}
}
}
impl<'de, M, A> DecodeBytes<'de, M, A> for Vec<u8, A>
where
A: Allocator,
{
const DECODE_BYTES_PACKED: bool = false;
#[inline]
fn decode_bytes<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
struct Visitor;
#[crate::trait_defaults(crate)]
impl<C> UnsizedVisitor<'_, C, [u8]> for Visitor
where
C: Context,
{
type Ok = Vec<u8, Self::Allocator>;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes")
}
#[inline]
fn visit_owned(
self,
_: C,
value: Vec<u8, Self::Allocator>,
) -> Result<Self::Ok, Self::Error> {
Ok(value)
}
#[inline]
fn visit_ref(self, cx: C, bytes: &[u8]) -> Result<Self::Ok, Self::Error> {
let mut buf = Vec::new_in(cx.alloc());
buf.extend_from_slice(bytes).map_err(cx.map())?;
Ok(buf)
}
}
decoder.decode_bytes(Visitor)
}
}
crate::internal::macros::slice_sequence! {
cx,
Vec<T, A>,
|| Vec::new_in(cx.alloc()),
|vec, value| vec.push(value).map_err(cx.map())?,
|vec, capacity| vec.reserve(capacity).map_err(cx.map())?,
|capacity| Vec::with_capacity_in(capacity, cx.alloc()).map_err(cx.map())?,
}