How would I create a handle manager in Rust? -


pub struct storage<t>{     vec: vec<t> } impl<t: clone> storage<t>{     pub fn new() -> storage<t>{         storage{vec: vec::new()}     }     pub fn get<'r>(&'r self, h: &handle<t>)-> &'r t{         let index = h.id;         &self.vec[index]     }     pub fn set(&mut self, h: &handle<t>, t: t){         let index = h.id;         self.vec[index] = t;     }     pub fn create(&mut self, t: t) -> handle<t>{         self.vec.push(t);         handle{id: self.vec.len()-1}     } } struct handle<t>{     id: uint } 

i trying create handle system in rust , have problems. code above simple example of want achieve.

the code works has 1 weakness.

let mut s1 = storage<uint>::new(); let mut s2 = storage<uint>::new(); let handle1 = s1.create(5); s1.get(handle1); // works s2.get(handle1); // unsafe 

i associate handle specific storage this

//pseudo code struct handle<t>{     id: uint,     storage: &storage<t> } impl<t> handle<t>{    pub fn get(&self) -> &t; } 

the problem rust doesn't allow this. if , create handle reference of storage wouldn't allowed mutate storage anymore.

i implement similar channel have clone t every time.

how express in rust?

the simplest way model use phantom type parameter on storage acts unique id, so:

use std::kinds::marker;  pub struct storage<id, t> {     marker: marker::invarianttype<id>,     vec: vec<t> }  impl<id, t> storage<id, t> {     pub fn new() -> storage<id, t>{         storage {             marker: marker::invarianttype,             vec: vec::new()         }     }      pub fn get<'r>(&'r self, h: &handle<id, t>) -> &'r t {         let index = h.id;         &self.vec[index]     }      pub fn set(&mut self, h: &handle<id, t>, t: t) {         let index = h.id;         self.vec[index] = t;     }      pub fn create(&mut self, t: t) -> handle<id, t> {         self.vec.push(t);         handle {             marker: marker::invariantlifetime,             id: self.vec.len() - 1         }     } }  pub struct handle<id, t> {     id: uint,     marker: marker::invarianttype<id> }  fn main() {     struct a; struct b;     let mut s1 = storage::<a, uint>::new();     let s2 = storage::<b, uint>::new();      let handle1 = s1.create(5);     s1.get(&handle1);      s2.get(&handle1); // won't compile, since != b } 

this solves problem in simplest case, has downsides. mainly, depends on use define , use of these different phantom types , prove unique. doesn't prevent bad behavior on user's part can use same phantom type multiple storage instances. in today's rust, however, best can do.

an alternative solution doesn't work today reasons i'll in later, might work later, uses lifetimes anonymous id types. code uses invariantlifetime marker, removes sub typing relationships other lifetimes lifetime uses.

here same system, rewritten use invariantlifetime instead of invarianttype:

use std::kinds::marker;  pub struct storage<'id, t> {     marker: marker::invariantlifetime<'id>,     vec: vec<t> }  impl<'id, t> storage<'id, t> {     pub fn new() -> storage<'id, t>{         storage {             marker: marker::invariantlifetime,             vec: vec::new()         }     }      pub fn get<'r>(&'r self, h: &handle<'id, t>) -> &'r t {         let index = h.id;         &self.vec[index]     }      pub fn set(&mut self, h: &handle<'id, t>, t: t) {         let index = h.id;         self.vec[index] = t;     }      pub fn create(&mut self, t: t) -> handle<'id, t> {         self.vec.push(t);         handle {             marker: marker::invariantlifetime,             id: self.vec.len() - 1         }     } }  pub struct handle<'id, t> {     id: uint,     marker: marker::invariantlifetime<'id> }  fn main() {     let mut s1 = storage::<uint>::new();     let s2 = storage::<uint>::new();      let handle1 = s1.create(5);     s1.get(&handle1);      // in theory won't compile, since lifetime of s2      // *slightly* shorter lifetime of s1.     //     // however, not how compiler works, , of today     // s2 gets same lifetime s1 (since can borrowed same period)     // , (unfortunately) compiles without error.     s2.get(&handle1); } 

in hypothetical future, assignment of lifetimes may change , may grow better mechanism sort of tagging. however, now, best way accomplish phantom types.


Comments

Popular posts from this blog

java - Plugin org.apache.maven.plugins:maven-install-plugin:2.4 or one of its dependencies could not be resolved -

Round ImageView Android -

How can I utilize Yahoo Weather API in android -