1
votes

Coming from another language I'm a little confused on how to do some basic stuff in Rust without breaking memory safety.

I'm trying to get references to a pair of elements stored in a Vec. Assume the elements stored in the Vec are large and I do not want to copy them:

struct Element {
  key: u64,
  data: SomeHugeType
}

In other languages (e.g. C++), I would just create two null pointers or something and loop over the vec like so:

const Element *ele1, *ele2;
ele1 = nullptr;
ele2 = nullptr;
for (auto const &ele : elements) {
      if (ele.key == key1) { ele1 = ele; }
      if (ele.key == key2) { ele2 = ele; }
      if (ele1 != nullptr && ele2 != nullptr) { break; }
}
if (ele1 == nullptr || ele2 == nullptr) { /* uh oh */}

But as far as I know I cannot do this in rust because I cannot have a reference to nothing (nullptr). I cannot borrow an element before I know which element I need to borrow.

How can I initialize some variable ele1 and ele2 before I find the actual elements they should reference in the Vec?

2

2 Answers

4
votes

To elaborate on Sebastian's answer, you can use None and Some(element) instead of nullptrs in C++:

type SomeHugeType = String;
struct Element {
    key: u64,
    data: SomeHugeType,
}

fn get_two_elems(elems: &Vec<Element>, key1: u64, key2: u64) -> Option<(&Element, &Element)> {
    let (mut elem1, mut elem2) = (None, None);
    for elem in elems {
        if elem.key == key1 {
            elem1 = Some(elem);
        } else if elem.key == key2 {
            elem2 = Some(elem)
        }
        if elem1.is_some() && elem2.is_some() {
            break;
        }
    }

    if let (Some(elem1), Some(elem2)) = (elem1, elem2) {
        Some((elem1, elem2))
    } else {
        None
    }
}

0
votes

You can have a reference to nothing. It's just the type Option<T&>