Refactor code base and split into more module files.
This commit is contained in:
parent
143861747d
commit
c03b162b7e
@ -1,6 +1,7 @@
|
|||||||
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
||||||
|
|
||||||
use crate::engine::{Array, Map, Module};
|
use crate::engine::{Array, Map};
|
||||||
|
use crate::module::Module;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
143
src/engine.rs
143
src/engine.rs
@ -3,19 +3,20 @@
|
|||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
|
use crate::module::Module;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
||||||
use crate::parser::{Expr, FnDef, ModuleRef, ReturnType, Stmt};
|
use crate::parser::{Expr, FnDef, ModuleRef, ReturnType, Stmt};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
use crate::utils::{calc_fn_def, StaticVec};
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
format,
|
format,
|
||||||
hash::{Hash, Hasher},
|
|
||||||
iter::once,
|
iter::once,
|
||||||
mem,
|
mem,
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
@ -26,12 +27,6 @@ use crate::stdlib::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
use crate::stdlib::collections::hash_map::DefaultHasher;
|
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
use ahash::AHasher;
|
|
||||||
|
|
||||||
/// An dynamic array of `Dynamic` values.
|
/// An dynamic array of `Dynamic` values.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_index` feature.
|
/// Not available under the `no_index` feature.
|
||||||
@ -42,32 +37,6 @@ pub type Array = Vec<Dynamic>;
|
|||||||
/// Not available under the `no_object` feature.
|
/// Not available under the `no_object` feature.
|
||||||
pub type Map = HashMap<String, Dynamic>;
|
pub type Map = HashMap<String, Dynamic>;
|
||||||
|
|
||||||
/// An imported module.
|
|
||||||
///
|
|
||||||
/// Not available under the `no_module` feature.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Module(HashMap<String, Dynamic>);
|
|
||||||
|
|
||||||
impl Module {
|
|
||||||
/// Create a new module.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self(HashMap::new())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Module {
|
|
||||||
type Target = HashMap<String, Dynamic>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Module {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
@ -166,78 +135,8 @@ impl<T: Into<Dynamic>> From<T> for Target<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type to hold a number of values in static storage for speed,
|
|
||||||
/// and any spill-overs in a `Vec`.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct StaticVec<T: Default + Clone> {
|
|
||||||
/// Total number of values held.
|
|
||||||
len: usize,
|
|
||||||
/// Static storage. 4 slots should be enough for most cases - i.e. four levels of indirection.
|
|
||||||
list: [T; 4],
|
|
||||||
/// Dynamic storage. For spill-overs.
|
|
||||||
more: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Clone> StaticVec<T> {
|
|
||||||
/// Create a new `StaticVec`.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
len: 0,
|
|
||||||
list: [
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
],
|
|
||||||
more: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Push a new value to the end of this `StaticVec`.
|
|
||||||
pub fn push<X: Into<T>>(&mut self, value: X) {
|
|
||||||
if self.len >= self.list.len() {
|
|
||||||
self.more.push(value.into());
|
|
||||||
} else {
|
|
||||||
self.list[self.len] = value.into();
|
|
||||||
}
|
|
||||||
self.len += 1;
|
|
||||||
}
|
|
||||||
/// Pop a value from the end of this `StaticVec`.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if the `StaticVec` is empty.
|
|
||||||
pub fn pop(&mut self) -> T {
|
|
||||||
let result = if self.len <= 0 {
|
|
||||||
panic!("nothing to pop!")
|
|
||||||
} else if self.len <= self.list.len() {
|
|
||||||
mem::replace(self.list.get_mut(self.len - 1).unwrap(), Default::default())
|
|
||||||
} else {
|
|
||||||
self.more.pop().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
self.len -= 1;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
/// Get the number of items in this `StaticVec`.
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
pub fn get(&self, index: usize) -> &T {
|
|
||||||
if index >= self.len {
|
|
||||||
panic!("index OOB in StaticVec");
|
|
||||||
}
|
|
||||||
|
|
||||||
if index < self.list.len() {
|
|
||||||
self.list.get(index).unwrap()
|
|
||||||
} else {
|
|
||||||
self.more.get(index - self.list.len()).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that holds all the current states of the Engine.
|
/// A type that holds all the current states of the Engine.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
/// Normally, access to variables are parsed with a relative offset into the scope to avoid a lookup.
|
/// Normally, access to variables are parsed with a relative offset into the scope to avoid a lookup.
|
||||||
/// In some situation, e.g. after running an `eval` statement, subsequent offsets may become mis-aligned.
|
/// In some situation, e.g. after running an `eval` statement, subsequent offsets may become mis-aligned.
|
||||||
@ -466,33 +365,6 @@ fn extract_prop_from_setter(fn_name: &str) -> Option<&str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a `u64` hash key from a function name and parameter types.
|
|
||||||
///
|
|
||||||
/// Parameter types are passed in via `TypeId` values from an iterator
|
|
||||||
/// which can come from any source.
|
|
||||||
pub fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>) -> u64 {
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
let mut s: AHasher = Default::default();
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
let mut s = DefaultHasher::new();
|
|
||||||
|
|
||||||
s.write(fn_name.as_bytes());
|
|
||||||
params.for_each(|t| t.hash(&mut s));
|
|
||||||
s.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculate a `u64` hash key from a function name and number of parameters (without regard to types).
|
|
||||||
pub(crate) fn calc_fn_def(fn_name: &str, params: usize) -> u64 {
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
let mut s: AHasher = Default::default();
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
let mut s = DefaultHasher::new();
|
|
||||||
|
|
||||||
s.write(fn_name.as_bytes());
|
|
||||||
s.write_usize(params);
|
|
||||||
s.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print/debug to stdout
|
/// Print/debug to stdout
|
||||||
fn default_print(s: &str) {
|
fn default_print(s: &str) {
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -503,12 +375,13 @@ fn default_print(s: &str) {
|
|||||||
fn search_scope<'a>(
|
fn search_scope<'a>(
|
||||||
scope: &'a mut Scope,
|
scope: &'a mut Scope,
|
||||||
name: &str,
|
name: &str,
|
||||||
modules: &Option<Box<StaticVec<(String, Position)>>>,
|
modules: &ModuleRef,
|
||||||
index: Option<NonZeroUsize>,
|
index: Option<NonZeroUsize>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
||||||
if let Some(modules) = modules {
|
if let Some(modules) = modules {
|
||||||
let (id, root_pos) = modules.get(0); // First module
|
let mut drain = modules.iter();
|
||||||
|
let (id, root_pos) = drain.next().unwrap(); // First module
|
||||||
|
|
||||||
let mut module = if let Some(index) = index {
|
let mut module = if let Some(index) = index {
|
||||||
scope
|
scope
|
||||||
@ -522,9 +395,7 @@ fn search_scope<'a>(
|
|||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos)))?
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
for x in 1..modules.len() {
|
for (id, id_pos) in drain {
|
||||||
let (id, id_pos) = modules.get(x);
|
|
||||||
|
|
||||||
module = module
|
module = module
|
||||||
.get_mut(id)
|
.get_mut(id)
|
||||||
.and_then(|v| v.downcast_mut::<Module>())
|
.and_then(|v| v.downcast_mut::<Module>())
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::{calc_fn_spec, Engine, FnCallArgs};
|
use crate::engine::{Engine, FnCallArgs};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
use crate::utils::calc_fn_spec;
|
||||||
|
|
||||||
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::ToString};
|
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::ToString};
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ mod error;
|
|||||||
mod fn_call;
|
mod fn_call;
|
||||||
mod fn_func;
|
mod fn_func;
|
||||||
mod fn_register;
|
mod fn_register;
|
||||||
|
mod module;
|
||||||
mod optimize;
|
mod optimize;
|
||||||
pub mod packages;
|
pub mod packages;
|
||||||
mod parser;
|
mod parser;
|
||||||
@ -83,9 +84,10 @@ mod result;
|
|||||||
mod scope;
|
mod scope;
|
||||||
mod stdlib;
|
mod stdlib;
|
||||||
mod token;
|
mod token;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
pub use any::Dynamic;
|
pub use any::Dynamic;
|
||||||
pub use engine::{calc_fn_spec as calc_fn_hash, Engine};
|
pub use engine::Engine;
|
||||||
pub use error::{ParseError, ParseErrorType};
|
pub use error::{ParseError, ParseErrorType};
|
||||||
pub use fn_call::FuncArgs;
|
pub use fn_call::FuncArgs;
|
||||||
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
||||||
@ -93,6 +95,7 @@ pub use parser::{AST, INT};
|
|||||||
pub use result::EvalAltResult;
|
pub use result::EvalAltResult;
|
||||||
pub use scope::Scope;
|
pub use scope::Scope;
|
||||||
pub use token::Position;
|
pub use token::Position;
|
||||||
|
pub use utils::calc_fn_spec as calc_fn_hash;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub use fn_func::Func;
|
pub use fn_func::Func;
|
||||||
|
35
src/module.rs
Normal file
35
src/module.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//! Module defining external-loaded modules for Rhai.
|
||||||
|
|
||||||
|
use crate::any::Dynamic;
|
||||||
|
|
||||||
|
use crate::stdlib::{
|
||||||
|
collections::HashMap,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
string::String,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An imported module.
|
||||||
|
///
|
||||||
|
/// Not available under the `no_module` feature.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Module(HashMap<String, Dynamic>);
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
/// Create a new module.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(HashMap::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Module {
|
||||||
|
type Target = HashMap<String, Dynamic>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Module {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
//! Main module defining the lexer and parser.
|
//! Main module defining the lexer and parser.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::engine::{calc_fn_def, Engine, FunctionsLib, StaticVec};
|
use crate::engine::{Engine, FunctionsLib};
|
||||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::{Position, Token, TokenIterator};
|
use crate::token::{Position, Token, TokenIterator};
|
||||||
|
use crate::utils::{calc_fn_def, StaticVec};
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -42,6 +43,9 @@ pub type FLOAT = f64;
|
|||||||
|
|
||||||
type PERR = ParseErrorType;
|
type PERR = ParseErrorType;
|
||||||
|
|
||||||
|
/// A chain of module names to qualify a variable or function call.
|
||||||
|
/// A `StaticVec` is used because most module-level access contains only one level,
|
||||||
|
/// and it is wasteful to always allocate a `Vec` with one element.
|
||||||
pub type ModuleRef = Option<Box<StaticVec<(String, Position)>>>;
|
pub type ModuleRef = Option<Box<StaticVec<(String, Position)>>>;
|
||||||
|
|
||||||
/// Compiled AST (abstract syntax tree) of a Rhai script.
|
/// Compiled AST (abstract syntax tree) of a Rhai script.
|
||||||
@ -1079,7 +1083,7 @@ fn parse_primary<'a>(
|
|||||||
vec.push((*id, pos));
|
vec.push((*id, pos));
|
||||||
modules = Some(Box::new(vec));
|
modules = Some(Box::new(vec));
|
||||||
|
|
||||||
let root = modules.as_ref().unwrap().get(0);
|
let root = modules.as_ref().unwrap().iter().next().unwrap();
|
||||||
index = stack.find_sub_scope(&root.0);
|
index = stack.find_sub_scope(&root.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1243,7 +1247,7 @@ fn make_dot_expr(
|
|||||||
}
|
}
|
||||||
// lhs.module::id - syntax error
|
// lhs.module::id - syntax error
|
||||||
(_, Expr::Variable(_, Some(modules), _, _)) => {
|
(_, Expr::Variable(_, Some(modules), _, _)) => {
|
||||||
return Err(PERR::PropertyExpected.into_err(modules.get(0).1))
|
return Err(PERR::PropertyExpected.into_err(modules.iter().next().unwrap().1))
|
||||||
}
|
}
|
||||||
// lhs.dot_lhs.dot_rhs
|
// lhs.dot_lhs.dot_rhs
|
||||||
(lhs, Expr::Dot(dot_lhs, dot_rhs, dot_pos)) => Expr::Dot(
|
(lhs, Expr::Dot(dot_lhs, dot_rhs, dot_pos)) => Expr::Dot(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module that defines the `Scope` type representing a function call-stack scope.
|
//! Module that defines the `Scope` type representing a function call-stack scope.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Union, Variant};
|
use crate::any::{Dynamic, Union, Variant};
|
||||||
use crate::engine::Module;
|
use crate::module::Module;
|
||||||
use crate::parser::{map_dynamic_to_expr, Expr};
|
use crate::parser::{map_dynamic_to_expr, Expr};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
|
||||||
|
128
src/utils.rs
Normal file
128
src/utils.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
//! Module containing various utility types and functions.
|
||||||
|
|
||||||
|
use crate::stdlib::{
|
||||||
|
any::TypeId,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
mem,
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
use crate::stdlib::collections::hash_map::DefaultHasher;
|
||||||
|
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
use ahash::AHasher;
|
||||||
|
|
||||||
|
/// Calculate a `u64` hash key from a function name and parameter types.
|
||||||
|
///
|
||||||
|
/// Parameter types are passed in via `TypeId` values from an iterator
|
||||||
|
/// which can come from any source.
|
||||||
|
pub fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>) -> u64 {
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
let mut s: AHasher = Default::default();
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
let mut s = DefaultHasher::new();
|
||||||
|
|
||||||
|
s.write(fn_name.as_bytes());
|
||||||
|
params.for_each(|t| t.hash(&mut s));
|
||||||
|
s.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate a `u64` hash key from a function name and number of parameters (without regard to types).
|
||||||
|
pub(crate) fn calc_fn_def(fn_name: &str, num_params: usize) -> u64 {
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
let mut s: AHasher = Default::default();
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
let mut s = DefaultHasher::new();
|
||||||
|
|
||||||
|
s.write(fn_name.as_bytes());
|
||||||
|
s.write_usize(num_params);
|
||||||
|
s.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type to hold a number of values in static storage for speed, and any spill-overs in a `Vec`.
|
||||||
|
///
|
||||||
|
/// This is essentially a knock-off of the [`staticvec`](https://crates.io/crates/staticvec) crate.
|
||||||
|
/// This simplified implementation here is to avoid pulling in another crate.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StaticVec<T: Default + Clone> {
|
||||||
|
/// Total number of values held.
|
||||||
|
len: usize,
|
||||||
|
/// Static storage. 4 slots should be enough for most cases - i.e. four levels of indirection.
|
||||||
|
list: [T; 4],
|
||||||
|
/// Dynamic storage. For spill-overs.
|
||||||
|
more: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default + Clone> StaticVec<T> {
|
||||||
|
/// Create a new `StaticVec`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
len: 0,
|
||||||
|
list: [
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
],
|
||||||
|
more: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Push a new value to the end of this `StaticVec`.
|
||||||
|
pub fn push<X: Into<T>>(&mut self, value: X) {
|
||||||
|
if self.len >= self.list.len() {
|
||||||
|
self.more.push(value.into());
|
||||||
|
} else {
|
||||||
|
self.list[self.len] = value.into();
|
||||||
|
}
|
||||||
|
self.len += 1;
|
||||||
|
}
|
||||||
|
/// Pop a value from the end of this `StaticVec`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the `StaticVec` is empty.
|
||||||
|
pub fn pop(&mut self) -> T {
|
||||||
|
let result = if self.len <= 0 {
|
||||||
|
panic!("nothing to pop!")
|
||||||
|
} else if self.len <= self.list.len() {
|
||||||
|
mem::replace(self.list.get_mut(self.len - 1).unwrap(), Default::default())
|
||||||
|
} else {
|
||||||
|
self.more.pop().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.len -= 1;
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
/// Get the number of items in this `StaticVec`.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.len
|
||||||
|
}
|
||||||
|
/// Get an item at a particular index.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the index is out of bounds.
|
||||||
|
pub fn get(&self, index: usize) -> &T {
|
||||||
|
if index >= self.len {
|
||||||
|
panic!("index OOB in StaticVec");
|
||||||
|
}
|
||||||
|
|
||||||
|
if index < self.list.len() {
|
||||||
|
self.list.get(index).unwrap()
|
||||||
|
} else {
|
||||||
|
self.more.get(index - self.list.len()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Get an iterator to entries in the `StaticVec`.
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||||
|
let num = if self.len >= self.list.len() {
|
||||||
|
self.list.len()
|
||||||
|
} else {
|
||||||
|
self.len
|
||||||
|
};
|
||||||
|
|
||||||
|
self.list[..num].iter().chain(self.more.iter())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user