bag_of_things/
bag_of_things.rs

1use orx_imp_vec::*;
2
3#[derive(Default)]
4struct Bag {
5    things: ImpVec<Thing>,
6}
7
8impl Bag {
9    fn push_thing(&self, name: &str) -> ThingInBag {
10        self.things.imp_push(Thing {
11            name: name.to_string(),
12        });
13        ThingInBag {
14            bag: self,
15            thing: &self.things[self.things.len() - 1],
16        }
17    }
18
19    fn things(&self) -> Vec<&str> {
20        self.things.iter().map(|x| x.name.as_str()).collect()
21    }
22}
23
24struct Thing {
25    name: String,
26}
27
28#[derive(Clone, Copy)]
29struct ThingInBag<'a> {
30    thing: &'a Thing,
31    bag: &'a Bag,
32}
33impl<'a> ThingInBag<'a> {
34    fn push_thing_in_same_bag(&self, name: &str) -> ThingInBag {
35        self.bag.push_thing(name)
36    }
37
38    fn is_in_bag(&self, bag: &Bag) -> bool {
39        let self_bag = self.bag as *const Bag;
40        let other_bag = bag as *const Bag;
41        self_bag == other_bag
42    }
43}
44impl<'a> PartialEq for ThingInBag<'a> {
45    fn eq(&self, other: &Self) -> bool {
46        let same_bag = self.bag as *const Bag == other.bag as *const Bag;
47        let same_thing = self.thing as *const Thing == other.thing as *const Thing;
48        same_bag && same_thing
49    }
50}
51
52fn main() {
53    // create a bag
54    let bag = Bag::default();
55
56    // add things and collect things in bag
57    let pen = bag.push_thing("pen");
58    let cup = bag.push_thing("cup");
59    assert_eq!(bag.things(), ["pen", "cup"]);
60
61    // add new things to bag using existing things in bag
62    pen.push_thing_in_same_bag("pencil");
63    cup.push_thing_in_same_bag("cupcake");
64    assert_eq!(bag.things(), ["pen", "cup", "pencil", "cupcake"]);
65
66    // create another bag
67    let other_bag = Bag::default();
68    let key = other_bag.push_thing("key");
69    let other_pen = other_bag.push_thing("pen");
70
71    // check if things belong to the same bag in constant time
72    assert_eq!(pen.is_in_bag(&bag), true);
73    assert_eq!(pen.is_in_bag(&other_bag), false);
74
75    assert_eq!(key.is_in_bag(&bag), false);
76    assert_eq!(key.is_in_bag(&other_bag), true);
77
78    // use referential equality to compare if two things are the same
79    assert!(pen != other_pen);
80}