#borrow #reference #ref #obj #object #versions #return

borrow_with_ref_obj

Versions of Borrow[Mut] that return reference objects (Ex. std::cell::Ref)

4 releases

Uses old Rust 2015

0.1.3 Oct 2, 2018
0.1.2 Oct 2, 2018
0.1.1 Oct 2, 2018
0.1.0 Oct 2, 2018

#2458 in Rust patterns

BSD-3-Clause

20KB
282 lines

Versions of the Borrow and BorrowMut traits that can return reference objects (such as std::cell::Ref) instead of references directly.

This allows you to accept T, &T, Rc<RefCell<T>>, Arc<Mutex<T>>, and Arc<RwLock<T>> by requiring a single trait.

See the crate documentation for more information.

Example

use borrow_with_ref_obj::BorrowWithRefObj;

/// Example structure that can possibly share ownership of a u32.
/// 
/// Modeled after a work queue getting data from a central source (ex. a
/// database) that may or may not be shared with others.
/// 
/// Note: Need to use higher-ranked trait bound here (for<'refr>), to tell
/// rust that the object that `borrow` returns about its lifetime.
struct Processor<Ref: for<'refr> BorrowWithRefObj<'refr, u32>> {
	/// Potentially-shared reference to a datum.
	/// Pretend this is a database connection or something like that.
	data_source: Ref,
	/// Queue of work to process
	work_queue: Vec<u32>,
}
impl<Ref: for<'refr> BorrowWithRefObj<'refr, u32>> Processor<Ref> {
	pub fn new(source: Ref) -> Self {
		Self {
			data_source: source,
			work_queue: vec![1,2,3,4,5],
		}
	}
	
	/// Processes one element in the work queue
	pub fn process_one(&mut self) {
		let current_work = match self.work_queue.pop() {
			Some(v) => v,
			None => { return; }
		};
		let data_source = self.data_source.borrow();
		let current_result = current_work + *data_source;
		println!("{}", current_result);
	}
	
	/// Processes all elements in the work queue
	pub fn process_all(&mut self) {
		while !self.work_queue.is_empty() {
			self.process_one();
		}
	}
}

// Create a processor that is the sole owner of the data
let mut sole_owning_processor = Processor::new(1);
// Prints 2,3,4,5,6
sole_owning_processor.process_all();

// Creates a processor that borrows the data
let value = 2;
let mut borrowing_processor = Processor::new(&value);
// Prints 3,4,5,6,7
sole_owning_processor.process_all();

// Creates a processor that shares ownership via Rc<RefCell<u32>>
use std::rc::Rc;
use std::cell::RefCell;

let value = Rc::new(RefCell::new(1));
let mut rc_processor = Processor::new(Rc::clone(&value));
// Prints 2,3,4
rc_processor.process_one();
rc_processor.process_one();
rc_processor.process_one();
// Modify the value
*value.borrow_mut() = 5;
// Prints 9,10
rc_processor.process_one();
rc_processor.process_one();

// You can do the same as above with Arc<Mutex<T>> or Arc<RwLock<T>>, if you
// need thread-safe access.

No runtime deps