MaybeOwned (a.k.a. SimpleCow) anywhere?


#1

So, I wrote a little struct for keeping track of something that can be borrowed or owned:

pub enum Has<'a, B> where B: 'a {
  Borrowed(&'a B),
  Owned(B),
}

impl<'a, B> Has<'a, B> {
  fn have(&self) -> &B {
    match *self {
      Has::Borrowed(b) => b,
      Has::Owned(ref b) => b,
    }
  }

  fn take(self) -> Option<B> {
    match self {
      Has::Borrowed(_) => None,
      Has::Owned(b) => Some(b),
    }
  }
}

With impls for Deref, AsRef, Borrow, Display, Debug, etc. just as you’d expect. Among other things, it’s useful for returning a member that might be mutated, while avoiding allocation if it’s not:

pub fn fancy_value(&self) -> Has<SomethingNotClone> {
  if self.value.is_fancy() {
    Borrowed(&self.value)
  } else {
    Owned(self.value.make_fancy_version())
  }
}

This is very much like Cow, except that it can operate on non-Clone / non-ToOwner targets, so long as they’re Sized.

First question: Is this problem already solved / is there something already like this somewhere? I looked around through the Rust API docs and book, did some web searches, but found nothing like this.

Secondly: Is this worth adding to std? It seems like this is a pretty handy thing to have, although there’s a lot of overlap with Cow.


#2

Calf ? :slight_smile:


#3

Note that you need some way to get an owned instance from a borrow to implement something like Cow correctly, and Clone types just have a blanket ToOwned impl. You can easily impl ToOwned for your types.


#4

True enough. Unless the type is not something you own. Or you don’t want to build a impl ToOwned when you know it’ll never be mutated. Etc. I admit that there’s not a huge body of use cases here, but I can still imagine scenarios where Cow doesn’t work as well.

Anyways, I’m not fighting hard to get this into std or anything. Mostly I just wanted to see if something like it already exists, but it looks like it doesn’t.


#5

This seems potentially useful. Did this ever get published as a crate? That may help see how useful it is to other developers.


#6

I think it would in theory be possible to change std::borrow::Cow to only require ToOwned for the methods that actually need it. You could still borrow instances for non-ToOwned types.

I believe this change would even be backwards-compatible.


#7

I don’t think it would be compatible, because then a generic function which needs ToOwned would have to spell that out explicitly, instead of getting it implicitly from Cow.