Skip to content

Commit

Permalink
add doc comments to Vec
Browse files Browse the repository at this point in the history
  • Loading branch information
DonIsaac committed Sep 24, 2024
1 parent 616948f commit 62c7b58
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
2 changes: 1 addition & 1 deletion crates/oxc_allocator/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serde::{Serialize, Serializer};

use crate::Allocator;

/// A Box without Drop.
/// A Box without [`Drop`].
/// This is used for over coming self-referential structs.
/// It is a memory leak if the boxed value has a `Drop` implementation.
pub struct Box<'alloc, T: ?Sized>(NonNull<T>, PhantomData<(&'alloc (), T)>);
Expand Down
48 changes: 48 additions & 0 deletions crates/oxc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
//! # ⚓ Oxc Memory Allocator
//!
//! Oxc uses a bump-based memory arena for faster AST allocations. This crate
//! contains an [`Allocator`] for creating such arenas, as well as ports of
//! memory management data types from `std` adapted to use this arena.
//!
//! ## No `Drop`s
//! Objects allocated into oxc memory arenas are never [`Dropped`](Drop), making
//! it relatively easy to leak memory if you're not careful. Memory is released
//! in bulk when the allocator is dropped.
//!
//! ## Examples
//! ```
//! use oxc_allocator::{Allocator, Box};
//!
//! struct Foo {
//! pub a: i32
//! }
//! impl std::ops::Drop for Foo {
//! fn drop(&mut self) {
//! // Arena boxes are never dropped.
//! unreachable!();
//! }
//! }
//!
//! let allocator = Allocator::default();
//! let foo = Box::new_in(Foo { a: 0 }, &allocator);
//! drop(foo);
//! ```
//!
//! Consumers of the [`oxc` umbrella crate](https://crates.io/crates/oxc) pass
//! [`Allocator`] references to other tools.
//!
//! ```
//! use oxc::{allocator::Allocator, parser::Parser, span::SourceType};
//!
//! let allocator = Allocator::default()
//! let parsed = Parser::new(&allocator, "let x = 1;", SourceType::default());
//! assert!(parsed.errors.is_empty());
//! ```

use std::{
convert::From,
ops::{Deref, DerefMut},
Expand All @@ -16,6 +57,13 @@ pub use clone_in::CloneIn;
pub use convert::{FromIn, IntoIn};
pub use vec::Vec;

/// A bump-allocated memory arena based on [bumpalo].
///
/// ## No `Drop`s
///
/// Objects that are bump-allocated will never have their [`Drop`] implementation
/// called &mdash; unless you do it manually yourself. This makes it relatively
/// easy to leak memory or other resources.
#[derive(Default)]
pub struct Allocator {
bump: Bump,
Expand Down
68 changes: 68 additions & 0 deletions crates/oxc_allocator/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,72 @@ use crate::Allocator;
pub struct Vec<'alloc, T>(vec::Vec<T, &'alloc Bump>);

impl<'alloc, T> Vec<'alloc, T> {
/// Constructs a new, empty `Vec<T>`.
///
/// The vector will not allocate until elements are pushed onto it.
///
/// # Examples
///
/// ```
/// use oxc_allocator::{Allocator, Vec};
///
/// let arena = Allocator::default();
///
/// let mut vec: Vec<i32> = Vec::new_in(&arena);
/// assert!(vec.is_empty());
/// ```
#[inline]
pub fn new_in(allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::new_in(allocator))
}

/// Constructs a new, empty `Vec<T>` with at least the specified capacity
/// with the provided allocator.
///
/// The vector will be able to hold at least `capacity` elements without
/// reallocating. This method is allowed to allocate for more elements than
/// `capacity`. If `capacity` is 0, the vector will not allocate.
///
/// It is important to note that although the returned vector has the
/// minimum *capacity* specified, the vector will have a zero *length*.
///
/// For `Vec<T>` where `T` is a zero-sized type, there will be no allocation
/// and the capacity will always be `usize::MAX`.
///
/// # Panics
///
/// Panics if the new capacity exceeds `isize::MAX` bytes.
///
/// # Examples
///
/// ```
/// use oxc_allocator::{Allocator, Vec};
///
/// let arena = Allocator::default();
///
/// let mut vec = Vec::with_capacity_in(10, &arena);
///
/// // The vector contains no items, even though it has capacity for more
/// assert_eq!(vec.len(), 0);
/// assert_eq!(vec.capacity(), 10);
///
/// // These are all done without reallocating...
/// for i in 0..10 {
/// vec.push(i);
/// }
/// assert_eq!(vec.len(), 10);
/// assert_eq!(vec.capacity(), 10);
///
/// // ...but this may make the vector reallocate
/// vec.push(11);
/// assert_eq!(vec.len(), 11);
/// assert!(vec.capacity() >= 11);
///
/// // A vector of a zero-sized type will always over-allocate, since no
/// // allocation is necessary
/// let vec_units = Vec::<()>::with_capacity_in(10, &arena);
/// assert_eq!(vec_units.capacity(), usize::MAX);
/// ```
#[inline]
pub fn with_capacity_in(capacity: usize, allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::with_capacity_in(capacity, allocator))
Expand Down Expand Up @@ -126,6 +187,13 @@ mod test {
use super::Vec;
use crate::Allocator;

#[test]
fn vec_with_capacity() {
let allocator = Allocator::default();
let v: Vec<i32> = Vec::with_capacity_in(10, &allocator);
assert!(v.is_empty());
}

#[test]
fn vec_debug() {
let allocator = Allocator::default();
Expand Down

0 comments on commit 62c7b58

Please sign in to comment.