How to implement easy NewType(usize) > usize coercions?

I want to implement a new type wrapper around a usize to help define an API.

But internally I want to be able to coerce this type into a usize as easily as possible. For example I'm using it for lots of array work, slicing, incrementing, etc:

  1. Take slices from an array[..newtype]
  2. Increment newtype += 1
  3. Compare to newtype < array.len()
  4. Etc

To this point I've been implementing each new trait as I need it Add, AddAssign, PartialEq, etc. And that started to get old... so I'm looking for an alternative.

I tried implementing AsRef<usize>, and that means I don't have to implement all the other traits, but then I have to sprinkle newtype.as_ref() all through my code.

Now I've just found Deref and that seems to do what I want and adds just * as extra syntax. But the trait documentation says it should only be used for smart pointers.

My questions... is it OK to use Deref for this case? Is there some better pattern that will also make this easy? Here's an example of the kind of code I want to write:

use std::ops::Deref;

pub struct Index(usize);

impl Deref for Index {
    type Target = usize;
    fn deref(&self) -> &usize {
        &self.0
    }
}

pub fn slice_array(items: &[u8], range: Range<Index>) -> &[u8] {
    assert!(items.len() >= *range.end);
    &items[*range.start..*range.end]
}

(Playground)

Last time I implemented newtypes for indexes, I went the opposite way. I also newtyped the container and made indexing on the new container type use the newtyped index directly. You can even make your own len and rely on derive to implement comparison between indexes. The purpose of this is to avoid any chance of mixing up different kinds of indexes (I had several in my case).

I feel that with Deref you loose the good things that newtypes provide: compiler verification of not mixing up indices.

I don't think it's wrong per say, but you should probably think about why you're using a newtype instead of usize in the first place.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.