88//!
99//! # Usage
1010//! ```
11- //! use data_structures::linked_list::block::{Block, Side};
11+ //! // use data_structures::linked_list::block::{Block, Side};
1212//!
13- //! let block_ptr = Block::new(10);
14- //! assert_eq!(*block_ptr.borrow().read_data(), Some(10));
13+ //! // let block_ptr = Block::new(10);
14+ //! // assert_eq!(*block_ptr.borrow().read_data(), Some(10));
1515//! ```
16- use std:: { cell:: RefCell , rc:: { Rc , Weak } } ;
16+ use std:: { cell:: RefCell , collections :: HashMap , iter :: Flatten , rc:: { Rc , Weak } } ;
1717
1818/// Direction of the pointer inside the Block
1919///
2020/// This enum is used to specify the direction of the pointer in a block of a doubly linked list.
2121/// It helps in identifying whether the pointer is pointing to the next block (Right) or the previous block (Left).
22- pub enum Side {
22+ #[ derive( Debug , Hash , Eq , PartialEq ) ]
23+ pub enum PointerName {
2324 Left ,
2425 Right ,
26+ Previous ,
27+ Next ,
28+ First ,
29+ Last ,
30+ Custom ( String ) , // Custom pointer name for more flexibility
2531}
2632
2733/// A block in a linked list
@@ -33,15 +39,14 @@ pub enum Side {
3339#[ derive( Debug ) ]
3440pub struct Block < T > {
3541 data : Option < T > ,
36- block_ref : Option < Weak < RefCell < Block < T > > > > , // reference to the block itself
37- right : Option < Rc < RefCell < Block < T > > > > , // points to the next block
38- left : Option < Rc < RefCell < Block < T > > > > , // points to the previous block
42+ self_ref : Option < Weak < RefCell < Block < T > > > > , // reference to the block itself
43+ pointers : HashMap < PointerName , Option < Rc < RefCell < Block < T > > > > > , // vector of pointers to other blocks
3944}
4045
4146impl < T > Block < T > {
4247 /// Create a new block with the given data and return a pointer to it
4348 /// # Arguments
44- /// * `data `: The data to be stored in the block. Tghe block takes ownership of the data.
49+ /// * `num_pointers `: The number of pointers to other blocks in the list
4550 ///
4651 /// # Returns
4752 /// A pointer to the newly created block.
@@ -50,23 +55,22 @@ impl<T> Block<T> {
5055 /// # Example
5156 /// ```
5257 /// use data_structures::linked_list::block::Block;
58+ /// use std::rc::Rc;
5359 ///
5460 /// let block_ptr = Block::new(10);
55- /// assert_eq!(*block_ptr.borrow().read_data(), Some(10));
5661 /// ```
5762 pub fn new ( data : T ) -> Rc < RefCell < Self > > {
5863 // Create new empty block
5964 let new_block_ptr = Rc :: new ( RefCell :: new ( Block {
6065 data : None ,
61- block_ref : None , // Temporariamente None
62- right : None ,
63- left : None ,
66+ self_ref : None , // Temporariamente None
67+ pointers : HashMap :: new ( ) ,
6468 } ) ) ;
6569
66- // Set the block_ref to point to itself
67- new_block_ptr. borrow_mut ( ) . block_ref = Some ( Rc :: downgrade ( & new_block_ptr) ) ;
70+ // Set the self_ref to point to itself
71+ new_block_ptr. borrow_mut ( ) . self_ref = Some ( Rc :: downgrade ( & new_block_ptr) ) ;
6872
69- // Set the data
73+ // Set the data in the new block
7074 new_block_ptr. borrow_mut ( ) . data = Some ( data) ;
7175
7276 new_block_ptr
@@ -86,7 +90,7 @@ impl<T> Block<T> {
8690 /// assert_eq!(Rc::strong_count(&new_block_ptr), 2);
8791 /// ```
8892 pub fn get_reference ( & self ) -> Rc < RefCell < Block < T > > > {
89- self . block_ref . as_ref ( ) . and_then ( |weak_ref| weak_ref. upgrade ( ) ) . unwrap ( )
93+ self . self_ref . as_ref ( ) . and_then ( |weak_ref| weak_ref. upgrade ( ) ) . unwrap ( )
9094 }
9195
9296 /// Get a reference to the data
@@ -124,8 +128,7 @@ impl<T> Block<T> {
124128 self . data . replace ( data)
125129 }
126130
127- /// Comsumes the block and returns the data
128- /// Returns the data and erase the pointer to the next and previous blocks
131+ /// Returns the data and erase all the pointers
129132 ///
130133 /// # Returns
131134 /// The data contained in the block
@@ -134,85 +137,79 @@ impl<T> Block<T> {
134137 /// ```
135138 /// use data_structures::linked_list::block::Block;
136139 /// let block_ptr = Block::new(10);
137- /// assert_eq!(block_ptr.borrow_mut().get_data (), Some(10));
140+ /// assert_eq!(block_ptr.borrow_mut().clear (), Some(10));
138141 /// ```
139142 ///
140- pub fn get_data ( & mut self ) -> Option < T > {
141- self . right = None ;
142- self . left = None ;
143- self . data . take ( )
144- }
143+ pub fn clear ( & mut self ) -> Option < T > {
144+ self . pointers . clear ( ) ;
145+ self . pointers = HashMap :: new ( ) ; // This was the only way I found to deallocate hasmap memory.
145146
146- /// Borrows the right pointer.
147- /// As a pattern, this method returns an Option of a Weak pointer to the right block.
148- /// Strong references could be created from the Weak pointer or the Block if needed.
149- ///
150- /// # Returns
151- /// A reference to the right pointer
152- ///
153- /// # Example
154- /// ```
155- /// use data_structures::linked_list::block::Block;
156- /// use data_structures::linked_list::block::Side;
157- ///
158- /// let block_ptr = Block::new(10);
159- /// assert_eq!(block_ptr.borrow().get_pointer(Side::Left).is_none(), true);
160- /// assert_eq!(block_ptr.borrow().get_pointer(Side::Right).is_none(), true);
161- /// ```
162- pub fn get_pointer ( & self , side : Side ) -> Option < Rc < RefCell < Block < T > > > > {
163- match side {
164- Side :: Left => self . left . clone ( ) ,
165- Side :: Right => self . right . clone ( ) ,
166- }
147+ self . self_ref . take ( ) ;
148+ self . data . take ( )
167149 }
168150
169- /// Replace the right pointer with a new block and return the old one
151+ /// Set a pointer in the Block.
152+ /// If the point already exists, it will be replaced with the new one and return the old pointer.
153+ ///
170154 /// # Arguments
171155 /// * `new_block_ptr`: The new block to be set as the right pointer
172156 /// # Returns
173157 /// The old right block pointer
174158 /// # Example
175159 /// ```
176160 /// use data_structures::linked_list::block::Block;
177- /// use data_structures::linked_list::block::Side ;
161+ /// use data_structures::linked_list::block::PointerName ;
178162 ///
179163 /// let block1_ptr = Block::new(10);
180164 /// let block2_ptr = Block::new(20);
181165 ///
182166 /// // Set the right pointer of block1 to block2
183- /// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(Some(&block2_ptr), Side::Right);
184- /// assert_eq!(block1_ptr.borrow().get_pointer(Side::Right).is_some(), true);
167+ /// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(PointerName::Left, Some(&block2_ptr));
185168 ///
186169 /// // Set the left pointer of block1 to block2
187- /// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(Some(&block2_ptr), Side::Left);
188- /// assert_eq!(block1_ptr.borrow().get_pointer(Side::Left).is_some(), true);
170+ /// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(PointerName::Right, Some(&block2_ptr));
189171 /// ```
190- pub fn set_pointer ( & mut self , new_block_ptr : Option < & Rc < RefCell < Block < T > > > > , side : Side ) -> Option < Rc < RefCell < Block < T > > > > {
172+ pub fn set_pointer ( & mut self , pointer_name : PointerName , new_block_ptr : Option < & Rc < RefCell < Block < T > > > > ) -> Option < Rc < RefCell < Block < T > > > > {
191173 match new_block_ptr {
192- Some ( new_block_ptr) => {
193- match side {
194- Side :: Left => {
195- self . left . replace ( new_block_ptr. clone ( ) )
196- }
197- Side :: Right => {
198- self . right . replace ( new_block_ptr. clone ( ) )
199- }
200- }
174+ Some ( new_ptr) => {
175+ self . pointers . insert ( pointer_name, Some ( new_ptr. clone ( ) ) ) . flatten ( )
201176 } ,
202177 None => {
203- match side {
204- Side :: Left => {
205- self . left . take ( )
206- }
207- Side :: Right => {
208- self . right . take ( )
209- }
210- }
178+ // If the pointer is None, remove it
179+ self . pointers . insert ( pointer_name, None ) . flatten ( )
211180 }
212181 }
213182 }
183+
184+ /// This method returns a new copy of a pointer in the Block increasing the pointer counter.
185+ ///
186+ /// # Returns
187+ /// A reference to the right pointer
188+ ///
189+ /// # Example
190+ /// ```
191+ /// use data_structures::linked_list::block::Block;
192+ /// use data_structures::linked_list::block::PointerName;
193+ ///
194+ /// let block_ptr = Block::new(10);
195+ /// let block_ptr2 = Block::new(20);
196+ ///
197+ /// block_ptr.borrow_mut().set_pointer(PointerName::Right, Some(&block_ptr2));
198+ ///
199+ /// assert!(block_ptr.borrow().get_pointer(PointerName::Left).is_none());
200+ /// assert!(block_ptr.borrow().get_pointer(PointerName::Right).is_some());
201+ /// ```
202+ pub fn get_pointer ( & self , pointer_name : PointerName ) -> Option < Rc < RefCell < Block < T > > > > {
203+ match self . pointers . get ( & pointer_name) {
204+ Some ( ptr) => {
205+ ptr. clone ( )
206+ }
207+ None => None // In this case there is no key with pointer_name.
208+ }
209+ }
214210}
215211
212+
216213#[ cfg( test) ]
217214mod tests {
218215 use super :: * ;
@@ -256,11 +253,11 @@ mod tests {
256253 let block2_ptr = Block :: new ( 20 ) ;
257254
258255 // Set the right pointer of block1 to block2
259- let mut right_block_ptr = block1_ptr. borrow_mut ( ) . set_pointer ( Some ( & block2_ptr) , Side :: Right ) ;
256+ let mut right_block_ptr = block1_ptr. borrow_mut ( ) . set_pointer ( PointerName :: Right , Some ( & block2_ptr) ) ;
260257 assert_eq ! ( right_block_ptr. is_none( ) , true ) ;
261258
262259 // Read the data of the right block
263- right_block_ptr = block1_ptr. borrow_mut ( ) . get_pointer ( Side :: Right ) ;
260+ right_block_ptr = block1_ptr. borrow_mut ( ) . get_pointer ( PointerName :: Right ) ;
264261 let binding = right_block_ptr. unwrap ( ) ;
265262 let binding = binding. borrow ( ) ;
266263 let right_block_data = binding. read_data ( ) ;
@@ -271,12 +268,4 @@ mod tests {
271268
272269 assert_eq ! ( * right_block_data, Some ( 20 ) ) ;
273270 }
274-
275- #[ test]
276- fn test_block_get_data ( ) {
277- let block_ptr = Block :: new ( 10 ) ;
278-
279- assert_eq ! ( block_ptr. borrow_mut( ) . get_data( ) , Some ( 10 ) ) ;
280- assert_eq ! ( block_ptr. borrow_mut( ) . get_data( ) , None ) ;
281- }
282271}
0 commit comments