1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::cargo)]
#![allow(unknown_lints)]
#![allow(clippy::manual_let_else)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![warn(missing_copy_implementations)]
#![warn(rust_2018_idioms)]
#![warn(rust_2021_compatibility)]
#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unused_qualifications)]
#![warn(variant_size_differences)]
// Enable feature callouts in generated documentation:
// https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html
//
// This approach is borrowed from tokio.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, feature(doc_alias))]

//! Contiguous growable vector types that implement the [Ruby `Array`] API.
//!
//! `Array` types are growable vectors with potentially heap-allocated contents.
//! The types in this crate can be passed by pointer over FFI.
//!
//! `Array` types implement the mutating APIs in the Ruby `Array` core class as
//! well as indexing and slicing APIs.
//!
//! `spinoso-array` is part of a [collection of crates] that implement the data
//! structures that comprise the Ruby Core and Standard Library implementation
//! for [Artichoke Ruby].
//!
//! # Array types
//!
//! - [`Array`] is based on [`Vec`] from the Rust `alloc` crate and standard
//!   library. This Spinoso array type is enabled by default.
#![cfg_attr(
    feature = "small-array",
    doc = "- [`SmallArray`] is based on [`SmallVec`] and implements the small vector"
)]
#![cfg_attr(
    feature = "small-array",
    doc = "  optimization – small arrays are stored inline without a heap allocation."
)]
#![cfg_attr(
    feature = "small-array",
    doc = "  This Spinoso array type requires the **small-array** Cargo feature."
)]
#![cfg_attr(
    feature = "tiny-array",
    doc = "- [`TinyArray`] is based on [`TinyVec`] and implements the small vector"
)]
#![cfg_attr(
    feature = "tiny-array",
    doc = "  optimization – small arrays are stored inline without a heap allocation."
)]
#![cfg_attr(
    feature = "tiny-array",
    doc = "  This Spinoso array type requires the **tiny-array** Cargo feature."
)]
//!
//!
//! # `no_std`
//!
//! This crate is `no_std` with a required dependency on the [`alloc`] crate.
//!
//! # Examples
//!
//! You can create an [`Array<T>`](Array) with [`new`](Array::new):
//!
//! ```
//! # use spinoso_array::Array;
//! let ary: Array<i32> = Array::new();
//! ```
//!
//! Or with one of the many [`From`] and [`FromIterator`] implementations:
//!
//! ```
//! # use core::iter;
//! # use spinoso_array::Array;
//! let ary: Array<i32> = Array::from(vec![1, 2, 3, 4]);
//! let ary2: Array<i32> = iter::repeat(1).take(10).collect();
//! ```
//!
//! You can [`push`](Array::push) values onto the end of an array (which will
//! grow the array as needed):
//!
//! ```
//! # use spinoso_array::Array;
//! let mut ary = Array::from(&[1, 2]);
//! ary.push(3);
//! ```
//!
//! Popping values behaves similarly:
//!
//! ```
//! # use spinoso_array::Array;
//! let mut ary = Array::from(&[1, 2]);
//! assert_eq!(ary.pop(), Some(2));
//! ```
//!
//! Arrays also support indexing (through the [`Index`] and [`IndexMut`]
//! traits):
//!
//! ```
//! # use spinoso_array::Array;
//! let mut a = Array::from(&[1, 2, 3]);
//! let three = a[2];
//! a[1] = a[1] + 5;
//! ```
//!
//! The `Array` vector types in this crate differ from [`Vec`] in the Rust `std`
//! by offering many specialized slicing and mutation APIs. For example, rather
//! than offering APIs like [`Vec::drain`] and [`Vec::splice`], array types in
//! this crate offer specialized methods like [`shift`], [`shift_n`],
//! [`unshift`], and [`unshift_n`] and `splice`-like methods with
//! [`insert_slice`], and [`set_slice`].
//!
//! ```
//! # use spinoso_array::Array;
//! let mut a = Array::from(&[1, 2, 3]);
//! a.unshift(0);
//! assert_eq!(a, [0, 1, 2, 3]);
//! let b = a.shift_n(10);
//! assert_eq!(a, []);
//! assert_eq!(b, [0, 1, 2, 3]);
//! ```
//!
//! # Panics
//!
//! `Array`s in this crate do not expose panicking slicing operations (except for
//! their [`Index`] and [`IndexMut`] implementations). Instead of panicking,
//! slicing APIs operate until the end of the vector or return `&[]`. Mutating
//! APIs extend `Array`s on out of bounds access.
//!
//! [Ruby `Array`]: https://ruby-doc.org/core-3.1.2/Array.html
//! [collection of crates]: https://crates.io/keywords/spinoso
//! [Artichoke Ruby]: https://www.artichokeruby.org/
//! [`Vec`]: alloc::vec::Vec
#![cfg_attr(feature = "small-array", doc = "[`SmallVec`]: smallvec::SmallVec")]
#![cfg_attr(feature = "tiny-array", doc = "[`TinyVec`]: tinyvec::TinyVec")]
//! [`From`]: core::convert::From
//! [`FromIterator`]: core::iter::FromIterator
//! [`Index`]: core::ops::Index
//! [`IndexMut`]: core::ops::IndexMut
//! [`Vec::drain`]: alloc::vec::Vec::drain
//! [`Vec::splice`]: alloc::vec::Vec::splice
//! [`shift`]: Array::shift
//! [`shift_n`]: Array::shift_n
//! [`unshift`]: Array::unshift
//! [`unshift_n`]: Array::unshift_n
//! [`insert_slice`]: Array::insert_slice
//! [`set_slice`]: Array::set_slice

// This crate is `no_std` + `alloc`
#![no_std]

// Ensure code blocks in `README.md` compile
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
mod readme {}

extern crate alloc;

mod array;

#[cfg(feature = "small-array")]
pub use array::smallvec::SmallArray;
#[cfg(feature = "tiny-array")]
pub use array::tinyvec::TinyArray;
pub use array::vec::{Array, RawParts};
#[cfg(any(feature = "small-array", feature = "tiny-array"))]
pub use array::INLINE_CAPACITY;