Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare definite-length arrays

Editor's note: This question was asked before Rust 1.0 and uses syntax which is no longer valid. Additionally, the specific problem in this question no longer occurs in Rust 1.0.

There is a struct that contains the only field, a fixed-width array of bytes. One would think that implementing traits from std::cmp for it would be straightforward, but deriving doesn't work:

#[deriving(Eq)]
pub struct ID {
    bytes: [u8, ..::constants::ID_SIZE]
}

src/id.rs:3:5: 3:40 error: mismatched types: expected `&&[u8]` but found `&[u8, .. 20]` ([] storage differs: expected `&` but found `20`)
src/id.rs:3     bytes: [u8, ..::constants::ID_SIZE]
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of #[deriving]
src/id.rs:1:1: 2:4 note: expansion site

The documentation suggests that Eq is implemented for &[] and ~[], not for fixed width array. Manual coercion to &[] doesn't work either:

impl Eq for ID {
    fn eq(&self, other: &ID) -> bool {
        (&self.bytes).eq(&other.bytes)
    }
}

src/id.rs:7:26: 7:38 error: mismatched types: expected `&&[u8, .. 20]` but found `&[u8, .. 20]` (expected &-ptr but found vector)
src/id.rs:7         (&self.bytes).eq(&other.bytes)
                                     ^~~~~~~~~~~~
src/id.rs:7:9: 7:39 error: failed to find an implementation of trait std::cmp::Eq for [u8, .. 20]
src/id.rs:7         (&self.bytes).eq(&other.bytes)
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This line in Rust reference manual may explain it:

Expressions producing vectors of definite size cannot be evaluated in a context expecting a vector of indefinite size; one must copy the definite-sized vector contents into a distinct vector of indefinite size.

The motivation is unclear, but I guess it has something to do with storing the length.

Anyway, is it possible to compare two fixed-lenght arrays using the implementation for &[], without copying?

like image 243
Michael Ivko Avatar asked Apr 18 '14 06:04

Michael Ivko


1 Answers

The documentation suggests that Eq is implemented for &[] and ~[], not for fixed width array.

Yes, that's because [T,..2] is a different type than [T,..3].

Anyway, is it possible to compare two fixed-lenght arrays using the implementation for &[], without copying?

Easily

impl Eq for ID {
    fn eq(&self, other: &ID) -> bool {
        self.bytes.iter().zip(other.bytes.iter()).all(|(a,b)| a == b) 
    }
}
like image 128
A.B. Avatar answered Nov 08 '22 07:11

A.B.