generic_pool/
lib.rs

1//! A pool for recycling allocated objects for later reuse. Uses generic get/put methods so you can store (almost) any type in a single pool instance.
2//!
3//! The main advantage of this library compared to other pools is that it can store and retrieve an __abritrary__ number of __different objects__ seemlessly.
4//! The pool itself does not contain any generics, only the get und put methods do. You initialise the pool and add any object to it that you want to recycle,
5//! and when you need them later on you just tell the pool which type of object you want. The internal implementation does all the magic of selecting the correct
6//! object type.
7//!
8//! This library is 100% pure Rust, uses no unstable or nighly only features and, most importantly, does not contain any unsafe code.
9//! It also has zero dependencies on default, but has an optional serde feature which enables
10//! de-/serialization of the configuration by [Serde](https://docs.serde.rs/serde/).
11//!
12//! ## Features
13//!
14//! - Provides a lightweigth __regular version__ as well as a thread-save __sync version__.
15//! - Does optionally provide a __drop guard__ which will automatically add objects back to the store after they go out of scope.
16//! - Allows configuring the maximum number of stored objects to prevent RAM exhaustion.
17//! - Allows configuring the rate at which the internal capacity gets increased over time.
18//! - Each configuration option can be set for each object type individually.
19//! - You can also set a fallback configuration for object types for which no constum configuration was set.
20//! - Provides optional auto-creation of objects which implement the [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) trait.
21//! - Offers cheap [`Clon`](https://doc.rust-lang.org/std/clone/trait.Clone.html)ing, so you can easily use the same pool in many places.
22//!
23//! ## A quick example
24//!
25//! This example demonstrates the most basic usage. We define two different structs, `Person` and `Animal`.
26//! We insert both of them into the pool and retrieve them later on. Note that the pool ensures that the correct object type gets returned.
27//!
28//! ```rust
29//! use generic_pool::Pool;
30//!
31//! #[derive(Debug, Default, Clone, Eq, PartialEq)]
32//! struct Person {
33//!     name: String,
34//!     age: i32,
35//! }
36//!
37//! #[derive(Debug, Default, Clone, Eq, PartialEq)]
38//! struct Animal {
39//!     home: bool,
40//!     name: String,
41//!     age_in_month: u64,
42//! }
43//!
44//! fn main() {
45//!     // Initialize the pool. Note that there is no need to specify any generic type parameters.
46//!     let mut pool = Pool::new();
47//!
48//!     let p = Person {
49//!         name: String::from("Mark"),
50//!         age: 100,
51//!     };
52//!
53//!     let a = Animal {
54//!         home: true,
55//!         name: String::from("Meow"),
56//!         age_in_month: 12,
57//!     };
58//!
59//!     // Add copies of the objects to the pool. Note that the pool takes any object.
60//!     pool.put(p.clone());
61//!     pool.put(a.clone());
62//!
63//!     // Retrieve the objects from the pool.
64//!     let person: Person = pool.get().unwrap(); // Returns `Option<Person>`.
65//!     let animal: Animal = pool.get_or_default(); // Returns `Animal`, but requires `Animal` to implement Default.
66//!
67//!     // The objects we retrieve are exactly the ones we put into the pool earlier.
68//!     assert_eq!(person, p);
69//!     assert_eq!(animal, a);
70//!
71//!     // NOTE: You should implement some kind of reset logic for objects saved in the pool.
72//!     // E.g.: person.reset()
73//! }
74//! ```
75//! ## Security
76//!
77//! The pool does not modify the objects it receives or gives out in any way, and does thus in particular not reset objects properly.
78//! __It is your responsibility to reset objects as appropriate either before adding them back to the store, or after receiving them.__
79//! Otherwise you will likely open up security holes by accidentaly using data from earlier operations.
80//!
81//! ### A common bad example
82//!
83//! Many frontend APIs do also provide priviledged access if they receive the proper credentials. Depending on the implementation the admin flag
84//! might only get explicitly set if some special credentials are send over. Without resetting the admin flag of recycled request objects this can
85//! open up a big security hole.
86//!
87//! ```ignore
88//! use generic_pool::Pool;
89//!
90//! struct FrontendRequest {
91//!     admin_credentials: Option<String>,
92//!     commands: Vec<String>,
93//! }
94//!
95//! #[derive(Default)]
96//! struct BackendRequest {
97//!     is_admin: bool,
98//!     commands: Vec<Command>,
99//! }
100//!
101//! fn main() {
102//!     let mut pool = Pool::new();
103//!
104//!     /* initialize API... */
105//!
106//!     loop {
107//!         // Retrieve a frontend request.
108//!         let frontend_req: FrontendRequest = get_frontend_req();
109//!
110//!         // Retrieve a recycled backend request object from the pool.
111//!         let mut backend_req = pool.get_or_default_with_guard::<BackendRequest>();
112//!
113//!         /* HAZARD - The backend request object might still contain older commands. */
114//!
115//!         // Parse the commands and check if they are known and valid.
116//!         for cmd in frountend_req.commands.iter() {
117//!             match parse_cmd(cmd) {
118//!                 Ok(parsed_cmd) => backend_req.commands.push(parsed_cmd),
119//!                 Err(err) => return_error_to_client_and_abort(err),
120//!             }
121//!         }
122//!
123//!         /* HAZARD - the backend request might still have the admin flag set!!! */
124//!
125//!         if let Some(credentials) = &frontend_req.admin_credentials {
126//!             match check_admin_credentials(credentials) {
127//!                 Ok(_) => backend_req.is_admin = true,
128//!                 Err(err) => return_error_to_client_and_abort(err),
129//!             }
130//!         }
131//!
132//!         // The backend might now receive unintended commands or even commands
133//!         // from unpriviledged users with the admin flag set.
134//!         send_backend_request(backend_req);
135//!
136//!         // NOTE: The drop guard of the backend request will put it back into the pool now.
137//!     }
138//! }
139//! ```
140//!
141//! ### The solution
142//!
143//! Of course a simple solution would be the implement the whole parsing and checking process in such a way that all fields of any recycled object get always filled
144//! with entirely new data, but this might not always be favorable. It can be difficult to check that all fields from all objects you recycle are overwritten before being used.
145//!
146//! The most secure solution is thus to write some explicit resetting logic for all objects you use and to make sure it gets called whenever you retrieve an object
147//! from the pool.
148//!
149//! ```ignore
150//! use generic_pool::{Pool, DropGuard};
151//!
152//! /// A local trait providing the reset logic for all recycled objects.
153//! trait Reset {
154//!     fn reset(self) -> Self; // See below why we use this pattern.
155//! }
156//!
157//! struct FrontendRequest {
158//!     admin_credentials: Option<String>,
159//!     commands: Vec<String>,
160//! }
161//!
162//! #[derive(Default)]
163//! struct BackendRequest {
164//!     is_admin: bool,
165//!     commands: Vec<Command>,
166//! }
167//!
168//! // We implement the trait on any drop guard by this.
169//! impl<G: AsMut<BackendRequest>> Reset for G {
170//!     fn reset(mut self) -> Self {
171//!         let req = self.as_mut();
172//!         req.is_admin = false;
173//!         req.commands.clear();
174//!
175//!         self
176//!     }
177//! }
178//!
179//! fn main() {
180//!     let mut pool = Pool::new();
181//!
182//!     /* initialize API... */
183//!
184//!     loop {
185//!         // Retrieve a frontend request.
186//!         let frontend_req: FrontendRequest = get_frontend_req();
187//!
188//!         // Retrieve a recycled backend request object from the pool.
189//!         let mut backend_req = match pool.get_with_guard::<BackendRequest>() {
190//!             Some(req) => req.reset(), // Is an expression, gives back req
191//!             None => DropGuard::new(BackendRequest::default(), &pool), // No need to reset
192//!         };
193//!
194//!         /* We can proceed safely now */
195//!     }
196//! }
197//! ```
198//!
199//! ## Configuration
200//!
201//! You can configure the maximum size of the stores internal buffers, as well as their initial size and the rate at which the capacity increases.
202//! These settings always apply to a specific type of object beeing stored in the pool, and never at
203//! the pool as a whole. That is if you store e.g. 2 different object types and configure a default
204//! maximum capacity of __1_000__, the pool will store up to __2_000__ objects. The settings are intended for limiting the memory usage of the pool.
205//!
206//! The pools fallback configuration will apply to all object types until you set a custom one for an object type. If you do not specify a costum
207//! fallback config for the pool, the pool will use the default values for [`Config`].
208//!
209//! ### Example
210//!
211//! ```rust
212//! use generic_pool::{Pool, Config};
213//!
214//! fn main() {
215//!     // Use a non-default config.
216//!     let config = Config {
217//!         max: 1_000,
218//!         step: 100,
219//!         start: 500,
220//!     };
221//!
222//!     assert_ne!(config, Config::default());
223//!
224//!     let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
225//!
226//!     // Alternative:
227//!     // let mut pool = Pool::new();
228//!     // pool.set_fallback_config(config);
229//!
230//!     assert_eq!(config, pool.fallback_config());
231//!     assert_eq!(config, pool.get_config::<Vec<u8>>());
232//!
233//!     // Create a costum config for `Vec<u8>`.
234//!     let custom_config = Config {
235//!         max: 100,
236//!         step: 10,
237//!         start: 10,
238//!     };
239//!
240//!     pool.set_config::<Vec<u8>>(custom_config);
241//!
242//!     assert_eq!(custom_config, pool.get_config::<Vec<u8>>());
243//! }
244//! ```
245use std::collections::HashMap;
246use std::sync::{Arc, RwLock};
247use std::rc::Rc;
248use std::cell::RefCell;
249use std::any::{Any, TypeId};
250use std::ops::{Deref, DerefMut};
251use std::fmt;
252use std::hash::{Hash, Hasher};
253
254#[cfg(feature = "serde")]
255use serde::{Deserialize, Serialize};
256
257
258
259#[cfg(test)]
260mod tests;
261
262
263
264/// The configuration options of the pools internal store.
265///
266/// The settings always apply to a specific type of object beeing stored in the pool, and never at
267/// the pool as a whole. That is if you store e.g. 2 different object types and configure a default
268/// maximum capacity of __1_000__, the pool will store up to __2_000__ objects.
269/// The settings are intended for limiting the memory usage of the pool.
270///
271/// The pools fallback configuration will apply to all object types until you set a custom one for an object type.
272/// If you do not specify a costum fallback config for the pool, the pool will use the default values for [`Config`].
273///
274/// We allow setting a [`max`](#structfield.max) capacity of the internal pool buffer. If the buffer is full
275/// and another object gets added to the pool, the new object will get dropped.
276///
277/// If a certain buffer gets created, it will use the [`start`](#structfield.start) value to configure its
278/// initial capacity. Whenever the capacity is reached and its length has not yet reached the
279/// [`max`](#structfield.max) value, the [`step`](#structfield.step) value is used to determine by which amount
280/// the capacity should be increased. Note that it will use a lower value then [`step`](#structfield.step)
281/// if otherwise the capacity would exceed the [`max`](#structfield.max) value.
282///
283/// # Example
284///
285/// ```rust
286/// use generic_pool::{Pool, Config};
287///
288/// fn main() {
289///     // Use a non-default config.
290///     let config = Config {
291///         max: 1_000,
292///         step: 100,
293///         start: 500,
294///     };
295///
296///     assert_ne!(config, Config::default());
297///
298///     let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
299///
300///     // Alternative:
301///     // let mut pool = Pool::new();
302///     // pool.set_fallback_config(config);
303///
304///     assert_eq!(config, pool.fallback_config());
305///     assert_eq!(config, pool.get_config::<Vec<u8>>());
306///
307///     // Create a costum config for `Vec<u8>`.
308///     let custom_config = Config {
309///         max: 100,
310///         step: 10,
311///         start: 10,
312///     };
313///
314///     pool.set_config::<Vec<u8>>(custom_config);
315///
316///     assert_eq!(custom_config, pool.get_config::<Vec<u8>>());
317/// }
318/// ```
319#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
321pub struct Config {
322    /// The maximum number of elements of a specific type to be hold inside the pool.
323    ///
324    /// __Default__: 100_000
325    pub max: usize,
326    /// The initial capacity for the storage of elements of a specific type.
327    ///
328    /// __Default__: 1_000
329    pub start: usize,
330    /// How much capacity to add to the storage of elements of a specific type if the storage
331    /// is full and has not yet reached the maximum.
332    ///
333    /// __Default__: 1_000
334    pub step: usize,
335}
336
337impl Default for Config {
338    fn default() -> Self {
339        Self {
340            max: 100_000,
341            start: 1_000,
342            step: 1_000,
343        }
344    }
345}
346
347impl fmt::Display for Config {
348    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349        write!(f, "Config {{max: {}, start: {}, step: {}}})", self.max, self.start, self.step)
350    }
351}
352
353impl Config {
354    /// Determines if we need to increase the capacity, and if so, by which amount.
355    fn next_step(&self, current_capacity: usize) -> Option<usize> {
356        if current_capacity>=self.max {
357            return None;
358        }
359
360        let remaining = self.max-current_capacity;
361
362        if remaining>=self.step {
363            return Some(self.step);
364        } else {
365            return Some(remaining);
366        }
367    }
368
369    /// Allocates more space if necessary, and returns an empty error if the
370    /// storage is full.
371    fn allocate_as_necessary<T>(&self, store: &mut Vec<T>) -> Result<(), ()> {
372        if store.len()>=self.max {
373            return Err(()); // The store is already full.
374        }
375
376        let capacity = store.capacity();
377
378        if capacity==store.len() {
379            if let Some(step) = self.next_step(capacity) {
380                store.reserve(step);
381            }
382        }
383
384        Ok(())
385    }
386}
387
388
389/// A smart pointer which automatically puts the contained object back into the [`Pool`] on drop.
390///
391/// This version is not thread-safe. For the thread-safe version take a look at [`SyncDropGuard`].
392#[derive(Debug)]
393pub struct DropGuard<T: Any> {
394    inner: Option<T>,
395    pool: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
396}
397
398impl<T: Any + Clone> Clone for DropGuard<T> {
399    fn clone(&self) -> Self {
400        Self {
401            inner: Clone::clone(&self.inner),
402            pool: Rc::clone(&self.pool),
403        }
404    }
405}
406
407impl<T: Any + PartialEq> PartialEq for DropGuard<T> {
408    fn eq(&self, other: &DropGuard<T>) -> bool {
409        self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
410    }
411}
412
413impl<T: Any + Eq> Eq for DropGuard<T> {}
414
415impl<T: Any + PartialOrd> PartialOrd for DropGuard<T> {
416    fn partial_cmp(&self, other: &DropGuard<T>) -> Option<std::cmp::Ordering> {
417        self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
418    }
419}
420
421impl<T: Any + Ord> Ord for DropGuard<T> {
422    fn cmp(&self, other: &DropGuard<T>) -> std::cmp::Ordering {
423        self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
424    }
425}
426
427/// The hash value corresponds to the hash value of the contained object.
428impl<T: Any + Hash> Hash for DropGuard<T> {
429    fn hash<H: Hasher>(&self, state: &mut H) {
430        self.inner.as_ref().unwrap().hash(state);
431    }
432}
433
434impl<T: Any + fmt::Display> fmt::Display for DropGuard<T> {
435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436        fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
437    }
438}
439
440impl<T: Any> DropGuard<T> {
441    /// Creates a new [`DropGuard`] from an abritrary object and adds the reference to a regular [`Pool`].
442    ///
443    /// # Example
444    ///
445    /// Creating a [`DropGuard`] yourself might be usefull if you want to use objects which
446    /// you want to manually create, but where you still want to have the auto-adding to the pool
447    /// once they go out of scope.
448    ///
449    /// ```rust
450    /// use generic_pool::{Pool, DropGuard};
451    ///
452    /// struct Buffer(Vec<u8>);
453    ///
454    /// impl Buffer {
455    ///     fn len(&self) -> usize {
456    ///         self.0.len()
457    ///     }
458    /// }
459    ///
460    /// fn main() {
461    ///     let mut pool = Pool::new();
462    ///
463    ///     // You use buffers which have a length of exactly 1kb.
464    ///     let buffer = match pool.get_with_guard::<Buffer>() {
465    ///         Some(buffer) => buffer,
466    ///         None => DropGuard::new(Buffer(vec![0u8; 1024]), &pool),
467    ///     };
468    ///
469    ///     assert_eq!(buffer.len(), 1024);
470    ///
471    ///     assert!(pool.get::<Buffer>().is_none());
472    ///     drop(buffer);
473    ///     let buffer = pool.get::<Buffer>().unwrap();
474    ///     assert_eq!(buffer.len(), 1024);
475    /// }
476    /// ```
477    pub fn new(obj: T, pool: &Pool) -> Self {
478        let inner = Some(obj);
479        let pool = Rc::clone(&pool.inner);
480        Self {
481            inner,
482            pool,
483        }
484    }
485
486    /// Consume this guard and return the contained object.
487    ///
488    /// Note that this is an associated function and not a method. See the example.
489    ///
490    /// # Example
491    ///
492    /// ```rust
493    /// use generic_pool::{Pool, DropGuard};
494    ///
495    /// struct Buffer(Vec<u8>);
496    ///
497    /// impl Buffer {
498    ///     fn len(&self) -> usize {
499    ///         self.0.len()
500    ///     }
501    /// }
502    ///
503    /// fn main() {
504    ///     let mut pool = Pool::new();
505    ///
506    ///     // You use buffers which have a length of exactly 1kb.
507    ///     let buffer = match pool.get_with_guard::<Buffer>() {
508    ///         Some(buffer) => buffer,
509    ///         None => DropGuard::new(Buffer(vec![0u8; 1024]), &pool),
510    ///     };
511    ///
512    ///     // Maybe you want to use the buffer for something else.
513    ///     let buffer: Buffer = DropGuard::into_inner(buffer);
514    ///     let mut buffer: Vec<u8> = buffer.0;
515    ///     buffer.clear();
516    ///
517    ///     assert_eq!(buffer.len(), 0);
518    /// }
519    /// ```
520    pub fn into_inner(mut guard: DropGuard<T>) -> T {
521        guard.inner.take().unwrap()
522    }
523}
524
525/// Ensures the contained value gets automatically added back to the [`Pool`] it came from.
526impl<T: Any> Drop for DropGuard<T> {
527    fn drop(&mut self) {
528        if let Some(obj) = self.inner.take() {
529            let obj = Box::new(obj);
530            if let Ok(mut pool) = self.pool.try_borrow_mut() {
531                pool.put::<T>(obj);
532            }
533        }
534    }
535}
536
537impl<T: Any> AsRef<T> for DropGuard<T> {
538    fn as_ref(&self) -> &T {
539        self.inner.as_ref().unwrap()
540    }
541}
542
543impl<T: Any> AsMut<T> for DropGuard<T> {
544    fn as_mut(&mut self) -> &mut T {
545        self.inner.as_mut().unwrap()
546    }
547}
548
549impl<T: Any> Deref for DropGuard<T> {
550    type Target = T;
551
552    fn deref(&self) -> &Self::Target {
553        self.as_ref()
554    }
555}
556
557impl<T: Any> DerefMut for DropGuard<T> {
558    fn deref_mut(&mut self) -> &mut Self::Target {
559        self.as_mut()
560    }
561}
562
563
564/// A smart pointer which automatically puts the contained object back into the [`SyncPool`] on drop.
565///
566/// This version is thread-safe. For the not thread-safe version take a look at [`DropGuard`].
567pub struct SyncDropGuard<T: Any + Send + Sync> {
568    inner: Option<T>,
569    pool: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
570}
571
572impl<T: Any + Send + Sync + Clone> Clone for SyncDropGuard<T> {
573    fn clone(&self) -> Self {
574        Self {
575            inner: Clone::clone(&self.inner),
576            pool: Arc::clone(&self.pool),
577        }
578    }
579}
580
581impl<T: Any + Send + Sync + PartialEq> PartialEq for SyncDropGuard<T> {
582    fn eq(&self, other: &SyncDropGuard<T>) -> bool {
583        self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
584    }
585}
586
587impl<T: Any + Send + Sync + Eq> Eq for SyncDropGuard<T> {}
588
589impl<T: Any + Send + Sync + PartialOrd> PartialOrd for SyncDropGuard<T> {
590    fn partial_cmp(&self, other: &SyncDropGuard<T>) -> Option<std::cmp::Ordering> {
591        self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
592    }
593}
594
595impl<T: Any + Send + Sync + Ord> Ord for SyncDropGuard<T> {
596    fn cmp(&self, other: &SyncDropGuard<T>) -> std::cmp::Ordering {
597        self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
598    }
599}
600
601/// The hash value corresponds to the hash value of the contained object.
602impl<T: Any + Send + Sync + Hash> Hash for SyncDropGuard<T> {
603    fn hash<H: Hasher>(&self, state: &mut H) {
604        self.inner.as_ref().unwrap().hash(state);
605    }
606}
607
608impl<T: Any + Send + Sync + fmt::Display> fmt::Display for SyncDropGuard<T> {
609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610        fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
611    }
612}
613
614impl<T: Any + Send + Sync> SyncDropGuard<T> {
615    /// Creates a new [`DropGuard`] from an abritrary object and adds the reference to a [`SyncPool`].
616    ///
617    /// # Example
618    ///
619    /// Creating a [`SyncDropGuard`] yourself might be usefull if you want to use objects which
620    /// you want to manually create, but where you still want to have the auto-adding to the pool
621    /// once they go out of scope.
622    ///
623    /// ```rust
624    /// use generic_pool::{SyncPool, SyncDropGuard};
625    ///
626    /// struct Buffer(Vec<u8>);
627    ///
628    /// impl Buffer {
629    ///     fn len(&self) -> usize {
630    ///         self.0.len()
631    ///     }
632    /// }
633    ///
634    /// fn main() {
635    ///     let mut pool = SyncPool::new();
636    ///
637    ///     // You use buffers which have a length of exactly 1kb.
638    ///     let buffer = match pool.get_with_guard::<Buffer>() {
639    ///         Some(buffer) => buffer,
640    ///         None => SyncDropGuard::new(Buffer(vec![0u8; 1024]), &pool),
641    ///     };
642    ///
643    ///     assert_eq!(buffer.len(), 1024);
644    ///
645    ///     assert!(pool.get::<Buffer>().is_none());
646    ///     drop(buffer);
647    ///     let buffer = pool.get::<Buffer>().unwrap();
648    ///     assert_eq!(buffer.len(), 1024);
649    /// }
650    /// ```
651    pub fn new(obj: T, pool: &SyncPool) -> Self {
652        let inner = Some(obj);
653        let pool = Arc::clone(&pool.inner);
654        Self {
655            inner,
656            pool,
657        }
658    }
659
660    /// Consume this guard and return the contained object.
661    ///
662    /// Note that this is an associated function and not a method. See the example.
663    ///
664    /// # Example
665    ///
666    /// ```rust
667    /// use generic_pool::{SyncPool, SyncDropGuard};
668    ///
669    /// struct Buffer(Vec<u8>);
670    ///
671    /// impl Buffer {
672    ///     fn len(&self) -> usize {
673    ///         self.0.len()
674    ///     }
675    /// }
676    ///
677    /// fn main() {
678    ///     let mut pool = SyncPool::new();
679    ///
680    ///     // You use buffers which have a length of exactly 1kb.
681    ///     let buffer = match pool.get_with_guard::<Buffer>() {
682    ///         Some(buffer) => buffer,
683    ///         None => SyncDropGuard::new(Buffer(vec![0u8; 1024]), &pool),
684    ///     };
685    ///
686    ///     // Maybe you want to use the buffer for something else.
687    ///     let buffer: Buffer = SyncDropGuard::into_inner(buffer);
688    ///     let mut buffer: Vec<u8> = buffer.0;
689    ///     buffer.clear();
690    ///
691    ///     assert_eq!(buffer.len(), 0);
692    /// }
693    /// ```
694    pub fn into_inner(mut guard: SyncDropGuard<T>) -> T {
695        guard.inner.take().unwrap()
696    }
697}
698
699/// Ensures the contained value gets automatically added back to the [`SyncPool`] it came from.
700impl<T: Any + Send + Sync> Drop for SyncDropGuard<T> {
701    fn drop(&mut self) {
702        if let Some(obj) = self.inner.take() {
703            let obj = Box::new(obj);
704            if let Ok(mut pool) = self.pool.write() {
705                pool.put::<T>(obj);
706            }
707        }
708    }
709}
710
711impl<T: Any + Send + Sync> AsRef<T> for SyncDropGuard<T> {
712    fn as_ref(&self) -> &T {
713        self.inner.as_ref().unwrap()
714    }
715}
716
717impl<T: Any + Send + Sync> AsMut<T> for SyncDropGuard<T> {
718    fn as_mut(&mut self) -> &mut T {
719        self.inner.as_mut().unwrap()
720    }
721}
722
723impl<T: Any + Send + Sync> Deref for SyncDropGuard<T> {
724    type Target = T;
725
726    fn deref(&self) -> &Self::Target {
727        self.as_ref()
728    }
729}
730
731impl<T: Any + Send + Sync> DerefMut for SyncDropGuard<T> {
732    fn deref_mut(&mut self) -> &mut Self::Target {
733        self.as_mut()
734    }
735}
736
737
738
739/// The internal structure for all pools we use. Contains all the magic implementation details.
740#[derive(Debug)]
741struct PoolInner<B> {
742    /// Contains the internal buffers, with each one holding one specific object type.
743    store: HashMap<TypeId, Vec<B>>,
744    /// Contains the custom configuration for each specific object type, if any.
745    config: HashMap<TypeId, Config>,
746    /// The default configuration for all object types which do not have a costum configuration.
747    fallback_config: Config,
748}
749
750impl<B> Default for PoolInner<B> {
751    fn default() -> Self {
752        Self {
753            store: HashMap::new(),
754            config: HashMap::new(),
755            fallback_config: Config::default(),
756        }
757    }
758}
759
760impl<B> fmt::Display for PoolInner<B> {
761    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762        write!(
763            f, "{{store: {} entries, config: {} entries, fallback_config: {}}}",
764            self.store.len(), self.config.len(),
765            self.fallback_config.to_string(),
766        )
767    }
768}
769
770impl<B> PoolInner<B> {
771    /// Retrieve the configuration for a specific object type.
772    pub fn get_config<T: Any>(&self) -> Config {
773        let id = TypeId::of::<T>();
774
775        match self.config.get(&id) {
776            Some(config) => config.clone(),
777            None => self.fallback_config,
778        }
779    }
780
781    /// Retrieve the fallback configuration for all object types with no costum configuration set.
782    pub fn fallback_config(&self) -> Config {
783        self.fallback_config
784    }
785
786    /// Sets the costum configuration for a specific object type.
787    pub fn set_config<T: Any>(&mut self, config: Config) {
788        let id = TypeId::of::<T>();
789
790        self.config.insert(id, config);
791    }
792
793    /// Deletes the costum configuration of a specific object type.
794    pub fn delete_config<T: Any>(&mut self) {
795        let id = TypeId::of::<T>();
796
797        self.config.remove(&id);
798    }
799
800    /// Sets the fallback configuration for all object types with no costum configuration set.
801    pub fn set_fallback_config(&mut self, config: Config) {
802        self.fallback_config = config;
803    }
804
805    /// Tries to retrieve an instance of a specific object type from the internal buffer.
806    pub fn get<T: Any>(&mut self) -> Option<B> {
807        let id = TypeId::of::<T>();
808
809        if let Some(list) = self.store.get_mut(&id) {
810            return list.pop();
811        }
812
813        return None
814    }
815
816    /// Tries to add an instance of a specific object type into the internal buffer.
817    pub fn put<T: Any>(&mut self, boxed_obj: B) {
818        let id = TypeId::of::<T>();
819
820        let config = match self.config.get(&id) {
821            Some(config) => config,
822            None => &self.fallback_config,
823        };
824
825        match self.store.get_mut(&id) {
826            Some(list) => {
827                if let Ok(_) = config.allocate_as_necessary(list) {
828                    list.push(boxed_obj);
829                }
830            }
831            None => {
832                let mut list = Vec::<B>::with_capacity(config.start);
833                list.push(boxed_obj);
834                self.store.insert(id, list);
835            }
836        }
837    }
838}
839
840
841
842/// A pool that allows storing abritrary objects.
843///
844/// This version is not thread-safe. For the thread-safe version take a look at [`SyncPool`].
845#[derive(Default)]
846pub struct Pool {
847    pub(crate) inner: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
848}
849
850/// The cloned [`Pool`] will still point to the same instance.
851impl Clone for Pool {
852    fn clone(&self) -> Self {
853        Self {
854            inner: Rc::clone(&self.inner),
855        }
856    }
857}
858
859impl fmt::Display for Pool {
860    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
861        write!(f, "Pool {}", self.inner.borrow().to_string())
862    }
863}
864
865impl Pool {
866    /// Creates a new [`Pool`] with the default fallback configuration.
867    ///
868    /// # Example
869    /// ```rust
870    /// use generic_pool::{Pool, Config};
871    ///
872    /// fn main() {
873    ///     let pool = Pool::new();
874    ///     // Equivalent:
875    ///     // let pool = Pool::default();
876    ///
877    ///     assert_eq!(pool.fallback_config(), Config::default());
878    /// }
879    /// ```
880    pub fn new() -> Self {
881        Self::default()
882    }
883
884    /// Create a new [`Pool`] with the provided [`Config`] as the fallback configuration.
885    ///
886    /// # Example
887    /// ```rust
888    /// use generic_pool::{Pool, Config};
889    ///
890    /// fn main() {
891    ///     // Use a non-default config.
892    ///     let config = Config {
893    ///         max: 1_000,
894    ///         step: 100,
895    ///         start: 500,
896    ///     };
897    ///
898    ///     assert_ne!(config, Config::default());
899    ///
900    ///     let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
901    ///
902    ///     assert_eq!(config, pool.fallback_config());
903    /// }
904    /// ```
905    pub fn with_fallback_config(config: Config) -> Self {
906        let mut pool = Self::default();
907        pool.set_fallback_config(config);
908
909        pool
910    }
911
912    /// Retrieve the currently active [`Config`] for the provided object type.
913    ///
914    /// If you have not manually set a [`Config`] for the provided object type, this method
915    /// will return the fallback configuration.
916    ///
917    /// # Example
918    /// ```rust
919    /// use generic_pool::{Pool, Config};
920    ///
921    /// fn main() {
922    ///     let mut pool = Pool::new();
923    ///
924    ///     let config = Config {
925    ///         max: 1_000,
926    ///         step: 100,
927    ///         start: 500,
928    ///     };
929    ///
930    ///     // Set the config for `Vec<u8>`.
931    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
932    ///
933    ///     // Retrieve the config for `Vec<u8>`.
934    ///     // We would get back the fallback config without the line above.
935    ///     let config_compare = pool.get_config::<Vec<u8>>();
936    ///
937    ///     assert_eq!(config_compare, config);
938    ///     assert_ne!(config_compare, pool.fallback_config());
939    /// }
940    /// ```
941    pub fn get_config<T: Any>(&self) -> Config {
942        self.inner.borrow().get_config::<T>()
943    }
944
945    /// Retrieve the fallback [`Config`] for all object types which do not have
946    /// a specific [`Config`] set.
947    ///
948    /// # Example
949    /// ```rust
950    /// use generic_pool::{Pool, Config};
951    ///
952    /// fn main() {
953    ///     // Use a non-default config.
954    ///     let config = Config {
955    ///         max: 1_000,
956    ///         step: 100,
957    ///         start: 500,
958    ///     };
959    ///
960    ///     assert_ne!(config, Config::default());
961    ///
962    ///     let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
963    ///
964    ///     assert_eq!(config, pool.fallback_config());
965    /// }
966    /// ```
967    pub fn fallback_config(&self) -> Config {
968        self.inner.borrow().fallback_config
969    }
970
971    /// Update the [`Config`] for the provided object type.
972    ///
973    /// # Example
974    /// ```rust
975    /// use generic_pool::{Pool, Config};
976    ///
977    /// fn main() {
978    ///     let mut pool = Pool::new();
979    ///
980    ///     let config = Config {
981    ///         max: 1_000,
982    ///         step: 100,
983    ///         start: 500,
984    ///     };
985    ///
986    ///     // Set the config for `Vec<u8>`.
987    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
988    ///
989    ///     // Retrieve the config for `Vec<u8>`.
990    ///     // We would get back the fallback config without the line above.
991    ///     let config_compare = pool.get_config::<Vec<u8>>();
992    ///
993    ///     assert_eq!(config_compare, config);
994    ///     assert_ne!(config_compare, pool.fallback_config());
995    /// }
996    /// ```
997    pub fn set_config<T: Any>(&mut self, config: Config) {
998        self.inner.borrow_mut().set_config::<T>(config);
999    }
1000
1001    /// Delete the costum [`Config`] for the provided object type.
1002    /// Afterwards the fallback config will apply again.
1003    ///
1004    /// # Example
1005    /// ```rust
1006    /// use generic_pool::{Pool, Config};
1007    ///
1008    /// fn main() {
1009    ///     let mut pool = Pool::new();
1010    ///
1011    ///     let config = Config {
1012    ///         max: 1_000,
1013    ///         step: 100,
1014    ///         start: 500,
1015    ///     };
1016    ///
1017    ///     // Set the config for `Vec<u8>`.
1018    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1019    ///
1020    ///     assert_eq!(pool.get_config::<Vec<u8>>(), config);
1021    ///
1022    ///     // Delete the costum config. Afterwards the fallback config will apply.
1023    ///     pool.delete_config::<Vec<u8>>();
1024    ///
1025    ///     assert_ne!(pool.get_config::<Vec<u8>>(), config);
1026    ///     assert_eq!(pool.get_config::<Vec<u8>>(), pool.fallback_config());
1027    /// }
1028    /// ```
1029    pub fn delete_config<T: Any>(&mut self) {
1030        self.inner.borrow_mut().delete_config::<T>();
1031    }
1032
1033    /// Set the fallback [`Config`] for all object types which do not have
1034    /// a specific [`Config`] set.
1035    ///
1036    /// # Example
1037    /// ```rust
1038    /// use generic_pool::{Pool, Config};
1039    ///
1040    /// fn main() {
1041    ///     // Start with the default config.
1042    ///     let mut pool = Pool::new();
1043    ///
1044    ///     // Create a non-default config.
1045    ///     let config = Config {
1046    ///         max: 1_000,
1047    ///         step: 100,
1048    ///         start: 500,
1049    ///     };
1050    ///
1051    ///     assert_ne!(config, pool.fallback_config());
1052    ///
1053    ///     pool.set_fallback_config(config);
1054    ///
1055    ///     assert_eq!(config, pool.fallback_config());
1056    /// }
1057    /// ```
1058    pub fn set_fallback_config(&mut self, config: Config) {
1059        self.inner.borrow_mut().fallback_config = config;
1060    }
1061
1062    /// Try to retrieve an object of the specified type. Will give back `None` if the there are no
1063    /// objects of this type currently stored in the pool.
1064    ///
1065    /// # Example
1066    ///
1067    /// ```rust
1068    /// use generic_pool::Pool;
1069    ///
1070    /// fn main() {
1071    ///     let mut pool = Pool::new();
1072    ///
1073    ///     let buffer = match pool.get::<Vec<u8>>() {
1074    ///         Some(mut buffer) => {
1075    ///             buffer.clear();
1076    ///             buffer
1077    ///         }
1078    ///         None => Vec::new(),
1079    ///     };
1080    ///
1081    ///     assert_eq!(buffer.len(), 0);
1082    /// }
1083    /// ```
1084    pub fn get<T: Any>(&mut self) -> Option<T> {
1085        if let Some(boxed_obj) = self.inner.borrow_mut().get::<T>() {
1086            if let Ok(element) = boxed_obj.downcast::<T>() {
1087                return Some(*element);
1088            }
1089        }
1090
1091        None
1092    }
1093
1094    /// Retrieve an object of the specified type. If there is no object of this type currently
1095    /// stored in the pool it will create one using its [`Default`] implementation.
1096    ///
1097    /// # Example
1098    ///
1099    /// ```rust
1100    /// use generic_pool::Pool;
1101    ///
1102    /// fn main() {
1103    ///     let mut pool = Pool::new();
1104    ///
1105    ///     let buffer = pool.get_or_default::<Vec<u8>>();
1106    ///
1107    ///     assert_eq!(buffer.len(), 0);
1108    /// }
1109    /// ```
1110    pub fn get_or_default<T: Any + Default>(&mut self) -> T {
1111        match self.get::<T>() {
1112            Some(obj) => {
1113                return obj
1114            }
1115            None => {
1116                return T::default()
1117            }
1118        }
1119    }
1120
1121    /// Try to retrieve an object of the specified type with a drop guard. Will give back `None`
1122    /// if the there are no objects of this type currently stored in the pool.
1123    ///
1124    /// Once the returned [`DropGuard`] - if any - goes out of scope it will automatically put
1125    /// the contained object pack into the pool. Note that the object might still get dropped
1126    /// by the pool if the corresponding internal buffer is full.
1127    ///
1128    /// # Example
1129    ///
1130    /// ```rust
1131    /// use generic_pool::{Pool, DropGuard};
1132    ///
1133    /// fn main() {
1134    ///     let mut pool = Pool::new();
1135    ///
1136    ///     let buffer: DropGuard<Vec<u8>> = match pool.get_with_guard::<Vec<u8>>() {
1137    ///         Some(mut buffer) => {
1138    ///             // DropGuard is a smart pointer, so we can call Vec.clear() directly.
1139    ///             buffer.clear();
1140    ///             buffer
1141    ///         }
1142    ///         None => DropGuard::new(Vec::new(), &pool),
1143    ///     };
1144    ///
1145    ///     assert_eq!(buffer.len(), 0);
1146    ///
1147    ///     assert!(pool.get::<Vec<u8>>().is_none());
1148    ///
1149    ///     // Will put the buffer back into the pool.
1150    ///     drop(buffer);
1151    ///
1152    ///     assert!(pool.get::<Vec<u8>>().is_some());
1153    /// }
1154    /// ```
1155    pub fn get_with_guard<T: Any>(&mut self) -> Option<DropGuard<T>> {
1156        match self.get::<T>() {
1157            Some(obj) => Some(DropGuard::new(obj, self)),
1158            None => None,
1159        }
1160    }
1161
1162    /// Retrieve an object of the specified type with a drop guard. If there is no object of this type currently
1163    /// stored in the pool it will create one using its [`Default`] implementation.
1164    ///
1165    /// Once the returned [`DropGuard`] goes out of scope it will automatically put
1166    /// the contained object pack into the pool. Note that the object might still get dropped
1167    /// by the pool if the corresponding internal buffer is full.
1168    ///
1169    /// # Example
1170    ///
1171    /// ```rust
1172    /// use generic_pool::{Pool, DropGuard};
1173    ///
1174    /// fn main() {
1175    ///     let mut pool = Pool::new();
1176    ///
1177    ///     let buffer: DropGuard<Vec<u8>> = pool.get_or_default_with_guard::<Vec<u8>>();
1178    ///
1179    ///     assert_eq!(buffer.len(), 0);
1180    ///
1181    ///     assert!(pool.get::<Vec<u8>>().is_none());
1182    ///
1183    ///     // Will put the buffer back into the pool.
1184    ///     drop(buffer);
1185    ///
1186    ///     assert!(pool.get::<Vec<u8>>().is_some());
1187    /// }
1188    /// ```
1189    pub fn get_or_default_with_guard<T: Any + Default>(&mut self) -> DropGuard<T> {
1190        let obj = self.get_or_default::<T>();
1191
1192        DropGuard::new(obj, self)
1193    }
1194
1195    /// Add an object to the pool. Unless the corresponding internal buffer is full, you can retrieve
1196    /// it later on by calling [`Pool.get()`](#method.get) or one of its variants.
1197    ///
1198    /// # Example
1199    ///
1200    /// ```rust
1201    /// use generic_pool::Pool;
1202    ///
1203    /// fn main() {
1204    ///     let mut pool = Pool::new();
1205    ///
1206    ///     assert!(pool.get::<Vec<u8>>().is_none());
1207    ///
1208    ///     pool.put(vec![0u8; 1024]);
1209    ///
1210    ///     let buffer = pool.get::<Vec<u8>>().unwrap();
1211    ///
1212    ///     assert_eq!(buffer.len(), 1024);
1213    /// }
1214    /// ```
1215    pub fn put<T: Any>(&mut self, obj: T) {
1216        let obj = Box::new(obj);
1217        self.inner.borrow_mut().put::<T>(obj);
1218    }
1219}
1220
1221
1222/// A thread-safe pool that allows storing abritrary objects.
1223///
1224/// This version is thread-safe. For the not thread-safe version take a look at [`Pool`].
1225#[derive(Default)]
1226pub struct SyncPool {
1227    pub(crate) inner: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
1228}
1229
1230/// The cloned [`SyncPool`] will still point to the same instance.
1231impl Clone for SyncPool {
1232    fn clone(&self) -> Self {
1233        Self {
1234            inner: Arc::clone(&self.inner),
1235        }
1236    }
1237}
1238
1239impl fmt::Display for SyncPool {
1240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1241        write!(f, "SyncPool {}", self.inner.read().unwrap().to_string())
1242    }
1243}
1244
1245impl SyncPool {
1246    /// Creates a new [`SyncPool`] with the default fallback configuration.
1247    ///
1248    /// # Example
1249    /// ```rust
1250    /// use generic_pool::{SyncPool, Config};
1251    ///
1252    /// fn main() {
1253    ///     let pool = SyncPool::new();
1254    ///     // Equivalent:
1255    ///     // let pool = SyncPool::default();
1256    ///
1257    ///     assert_eq!(pool.fallback_config(), Config::default());
1258    /// }
1259    /// ```
1260    pub fn new() -> Self {
1261        Self::default()
1262    }
1263
1264    /// Create a new [`SyncPool`] with the provided [`Config`] as the fallback configuration.
1265    ///
1266    /// # Example
1267    /// ```rust
1268    /// use generic_pool::{SyncPool, Config};
1269    ///
1270    /// fn main() {
1271    ///     // Use a non-default config.
1272    ///     let config = Config {
1273    ///         max: 1_000,
1274    ///         step: 100,
1275    ///         start: 500,
1276    ///     };
1277    ///
1278    ///     assert_ne!(config, Config::default());
1279    ///
1280    ///     let mut pool = SyncPool::with_fallback_config(config); // NOTE Config implements Copy.
1281    ///
1282    ///     assert_eq!(config, pool.fallback_config());
1283    /// }
1284    /// ```
1285    pub fn with_fallback_config(config: Config) -> Self {
1286        let mut pool = Self::default();
1287        pool.set_fallback_config(config);
1288
1289        pool
1290    }
1291
1292    /// Retrieve the currently active [`Config`] for the provided object type.
1293    ///
1294    /// If you have not manually set a [`Config`] for the provided object type, this method
1295    /// will return the fallback configuration.
1296    ///
1297    /// # Example
1298    /// ```rust
1299    /// use generic_pool::{SyncPool, Config};
1300    ///
1301    /// fn main() {
1302    ///     let mut pool = SyncPool::new();
1303    ///
1304    ///     let config = Config {
1305    ///         max: 1_000,
1306    ///         step: 100,
1307    ///         start: 500,
1308    ///     };
1309    ///
1310    ///     // Set the config for `Vec<u8>`.
1311    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1312    ///
1313    ///     // Retrieve the config for `Vec<u8>`.
1314    ///     // We would get back the fallback config without the line above.
1315    ///     let config_compare = pool.get_config::<Vec<u8>>();
1316    ///
1317    ///     assert_eq!(config_compare, config);
1318    ///     assert_ne!(config_compare, pool.fallback_config());
1319    /// }
1320    /// ```
1321    pub fn get_config<T: Any + Send + Sync>(&mut self) -> Config {
1322        let inner = self.inner.read().unwrap();
1323        inner.get_config::<T>()
1324    }
1325
1326    /// Retrieve the fallback [`Config`] for all object types which do not have
1327    /// a specific [`Config`] set.
1328    ///
1329    /// # Example
1330    /// ```rust
1331    /// use generic_pool::{SyncPool, Config};
1332    ///
1333    /// fn main() {
1334    ///     // Use a non-default config.
1335    ///     let config = Config {
1336    ///         max: 1_000,
1337    ///         step: 100,
1338    ///         start: 500,
1339    ///     };
1340    ///
1341    ///     assert_ne!(config, Config::default());
1342    ///
1343    ///     let mut pool = SyncPool::with_fallback_config(config); // NOTE Config implements Copy.
1344    ///
1345    ///     assert_eq!(config, pool.fallback_config());
1346    /// }
1347    /// ```
1348    pub fn fallback_config(&self) -> Config {
1349        let inner = self.inner.read().unwrap();
1350        inner.fallback_config()
1351    }
1352
1353    /// Update the [`Config`] for the provided object type.
1354    ///
1355    /// # Example
1356    /// ```rust
1357    /// use generic_pool::{SyncPool, Config};
1358    ///
1359    /// fn main() {
1360    ///     let mut pool = SyncPool::new();
1361    ///
1362    ///     let config = Config {
1363    ///         max: 1_000,
1364    ///         step: 100,
1365    ///         start: 500,
1366    ///     };
1367    ///
1368    ///     // Set the config for `Vec<u8>`.
1369    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1370    ///
1371    ///     // Retrieve the config for `Vec<u8>`.
1372    ///     // We would get back the fallback config without the line above.
1373    ///     let config_compare = pool.get_config::<Vec<u8>>();
1374    ///
1375    ///     assert_eq!(config_compare, config);
1376    ///     assert_ne!(config_compare, pool.fallback_config());
1377    /// }
1378    /// ```
1379    pub fn set_config<T: Any + Send + Sync>(&mut self, config: Config) {
1380        let mut inner = self.inner.write().unwrap();
1381        inner.set_config::<T>(config);
1382    }
1383
1384    /// Delete the costum [`Config`] for the provided object type.
1385    /// Afterwards the fallback config will apply again.
1386    ///
1387    /// # Example
1388    /// ```rust
1389    /// use generic_pool::{SyncPool, Config};
1390    ///
1391    /// fn main() {
1392    ///     let mut pool = SyncPool::new();
1393    ///
1394    ///     let config = Config {
1395    ///         max: 1_000,
1396    ///         step: 100,
1397    ///         start: 500,
1398    ///     };
1399    ///
1400    ///     // Set the config for `Vec<u8>`.
1401    ///     pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1402    ///
1403    ///     assert_eq!(pool.get_config::<Vec<u8>>(), config);
1404    ///
1405    ///     // Delete the costum config. Afterwards the fallback config will apply.
1406    ///     pool.delete_config::<Vec<u8>>();
1407    ///
1408    ///     assert_ne!(pool.get_config::<Vec<u8>>(), config);
1409    ///     assert_eq!(pool.get_config::<Vec<u8>>(), pool.fallback_config());
1410    /// }
1411    /// ```
1412    pub fn delete_config<T: Any>(&mut self) {
1413        let mut inner = self.inner.write().unwrap();
1414        inner.delete_config::<T>();
1415    }
1416
1417    /// Set the fallback [`Config`] for all object types which do not have
1418    /// a specific [`Config`] set.
1419    ///
1420    /// # Example
1421    /// ```rust
1422    /// use generic_pool::{SyncPool, Config};
1423    ///
1424    /// fn main() {
1425    ///     // Start with the default config.
1426    ///     let mut pool = SyncPool::new();
1427    ///
1428    ///     // Create a non-default config.
1429    ///     let config = Config {
1430    ///         max: 1_000,
1431    ///         step: 100,
1432    ///         start: 500,
1433    ///     };
1434    ///
1435    ///     assert_ne!(config, pool.fallback_config());
1436    ///
1437    ///     pool.set_fallback_config(config);
1438    ///
1439    ///     assert_eq!(config, pool.fallback_config());
1440    /// }
1441    /// ```
1442    pub fn set_fallback_config(&mut self, config: Config) {
1443        let mut inner = self.inner.write().unwrap();
1444        inner.set_fallback_config(config);
1445    }
1446
1447    /// Try to retrieve an object of the specified type. Will give back `None` if the there are no
1448    /// objects of this type currently stored in the pool.
1449    ///
1450    /// # Example
1451    ///
1452    /// ```rust
1453    /// use generic_pool::SyncPool;
1454    ///
1455    /// fn main() {
1456    ///     let mut pool = SyncPool::new();
1457    ///
1458    ///     let buffer = match pool.get::<Vec<u8>>() {
1459    ///         Some(mut buffer) => {
1460    ///             buffer.clear();
1461    ///             buffer
1462    ///         }
1463    ///         None => Vec::new(),
1464    ///     };
1465    ///
1466    ///     assert_eq!(buffer.len(), 0);
1467    /// }
1468    /// ```
1469    pub fn get<T: Any + Send + Sync>(&self) -> Option<T> {
1470        let mut inner = self.inner.write().unwrap();
1471        if let Some(boxed_obj) = inner.get::<T>() {
1472            if let Ok(element) = boxed_obj.downcast::<T>() {
1473                return Some(*element);
1474            }
1475        }
1476
1477        None
1478    }
1479
1480    /// Retrieve an object of the specified type. If there is no object of this type currently
1481    /// stored in the pool it will create one using its [`Default`] implementation.
1482    ///
1483    /// # Example
1484    ///
1485    /// ```rust
1486    /// use generic_pool::SyncPool;
1487    ///
1488    /// fn main() {
1489    ///     let mut pool = SyncPool::new();
1490    ///
1491    ///     let buffer = pool.get_or_default::<Vec<u8>>();
1492    ///
1493    ///     assert_eq!(buffer.len(), 0);
1494    /// }
1495    /// ```
1496    pub fn get_or_default<T: Any + Send + Sync + Default>(&self) -> T {
1497        match self.get::<T>() {
1498            Some(obj) => {
1499                return obj
1500            }
1501            None => {
1502                return T::default()
1503            }
1504        }
1505    }
1506
1507    /// Try to retrieve an object of the specified type with a drop guard. Will give back `None`
1508    /// if the there are no objects of this type currently stored in the pool.
1509    ///
1510    /// Once the returned [`SyncDropGuard`] - if any - goes out of scope it will automatically put
1511    /// the contained object pack into the pool. Note that the object might still get dropped
1512    /// by the pool if the corresponding internal buffer is full.
1513    ///
1514    /// # Example
1515    ///
1516    /// ```rust
1517    /// use generic_pool::{SyncPool, SyncDropGuard};
1518    ///
1519    /// fn main() {
1520    ///     let mut pool = SyncPool::new();
1521    ///
1522    ///     let buffer: SyncDropGuard<Vec<u8>> = match pool.get_with_guard::<Vec<u8>>() {
1523    ///         Some(mut buffer) => {
1524    ///             // DropGuard is a smart pointer, so we can call Vec.clear() directly.
1525    ///             buffer.clear();
1526    ///             buffer
1527    ///         }
1528    ///         None => SyncDropGuard::new(Vec::new(), &pool),
1529    ///     };
1530    ///
1531    ///     assert_eq!(buffer.len(), 0);
1532    ///
1533    ///     assert!(pool.get::<Vec<u8>>().is_none());
1534    ///
1535    ///     // Will put the buffer back into the pool.
1536    ///     drop(buffer);
1537    ///
1538    ///     assert!(pool.get::<Vec<u8>>().is_some());
1539    /// }
1540    /// ```
1541    pub fn get_with_guard<T: Any + Send + Sync>(&mut self) -> Option<SyncDropGuard<T>> {
1542        match self.get::<T>() {
1543            Some(obj) => Some(SyncDropGuard::new(obj, self)),
1544            None => None,
1545        }
1546    }
1547
1548    /// Retrieve an object of the specified type with a drop guard. If there is no object of this type currently
1549    /// stored in the pool it will create one using its [`Default`] implementation.
1550    ///
1551    /// Once the returned [`SyncDropGuard`] goes out of scope it will automatically put
1552    /// the contained object pack into the pool. Note that the object might still get dropped
1553    /// by the pool if the corresponding internal buffer is full.
1554    ///
1555    /// # Example
1556    ///
1557    /// ```rust
1558    /// use generic_pool::{SyncPool, SyncDropGuard};
1559    ///
1560    /// fn main() {
1561    ///     let mut pool = SyncPool::new();
1562    ///
1563    ///     let buffer: SyncDropGuard<Vec<u8>> = pool.get_or_default_with_guard::<Vec<u8>>();
1564    ///
1565    ///     assert_eq!(buffer.len(), 0);
1566    ///
1567    ///     assert!(pool.get::<Vec<u8>>().is_none());
1568    ///
1569    ///     // Will put the buffer back into the pool.
1570    ///     drop(buffer);
1571    ///
1572    ///     assert!(pool.get::<Vec<u8>>().is_some());
1573    /// }
1574    /// ```
1575    pub fn get_or_default_with_guard<T: Any + Send + Sync + Default>(&mut self) -> SyncDropGuard<T> {
1576        let obj = self.get_or_default::<T>();
1577
1578        SyncDropGuard::new(obj, self)
1579    }
1580
1581    /// Add an object to the pool. Unless the corresponding internal buffer is full, you can retrieve
1582    /// it later on by calling [`SyncPool.get()`](#method.get) or one of its variants.
1583    ///
1584    /// # Example
1585    ///
1586    /// ```rust
1587    /// use generic_pool::SyncPool;
1588    ///
1589    /// fn main() {
1590    ///     let mut pool = SyncPool::new();
1591    ///
1592    ///     assert!(pool.get::<Vec<u8>>().is_none());
1593    ///
1594    ///     pool.put(vec![0u8; 1024]);
1595    ///
1596    ///     let buffer = pool.get::<Vec<u8>>().unwrap();
1597    ///
1598    ///     assert_eq!(buffer.len(), 1024);
1599    /// }
1600    /// ```
1601    pub fn put<T: Any + Send + Sync>(&self, obj: T) {
1602        let obj = Box::new(obj);
1603        let mut inner = self.inner.write().unwrap();
1604        inner.put::<T>(obj);
1605    }
1606}