wavesinaroom
wavesinaroom

Reputation: 191

Assert struct vector length

My very first project in rust is a small poker like card game that has five columns players put five cards in. Card is a struct that fetches its value and suite from an external API. Board on the other hand, stores the columns I talked about earlier. Now, I want to test that a Board column doesn't get more than five cards by running a test.

Card:

pub struct Card {
    value: String,
    suit: String,
}

impl Card {
    pub fn new(value: String, suit: String) -> Card {
        Card { value, suit }
    }
}

Board:

use crate::card::Card;

struct Board {
    columns: [Vec<Card>;5]
}

impl Board {
    fn add_card(self){# adds a card}

Test:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn no_card_full_column() {
        let card_one = Card::new(String::from("4"), String::from("Spades"));
        let card_two = Card::new(String::from("3"), String::from("Spades"));
        let card_three = Card::new(String::from("2"), String::from("Spades"));
        let card_four = Card::new(String::from("5"), String::from("Spades"));
        let card_five = Card::new(String::from("6"), String::from("Spades"));
        let mut board = Board {
            columns: [vec![], vec![], vec![], vec![], vec![]],
        };
        board.columns[0].push(card_one);
        board.columns[0].push(card_two);
        board.columns[0].push(card_three);
        board.columns[0].push(card_four);
        board.columns[0].push(card_five);

        board.add_card();
        assert_eq!(&board.columns[0].len(), 5);
    }
}

rust-analyzer complains with can't compare &usize with integer (I'm aware of the usize borrow btw) so I've got a couple of questions:

  1. Do struct vectors allocate memory in a different way that uses usize instead of integer?
  2. I researched docs but didn't get anything I could use so I tried to cast usize to integer, I know that's not elegant but I wanted to pass the test and improve it later (green, red, refactor). I don't feel that casting the length is the answer. Should I still keep tying though?

Upvotes: -1

Views: 47

Answers (1)

啊鹿Dizzyi
啊鹿Dizzyi

Reputation: 1050

The compiler is complaining that you are comparing a reference to a value, because you are comparing &_ to _, is like doing &420 == 69 (&i32 to i32).

So just remove the &

assert_eq!(board.columns[0].len(), 5);

I suspect the reason you added a & in the first place is because of this error message.

error[E0382]: borrow of moved value: `board`
  --> ***\src/main.rs:36:16
   |
26 |     let mut board = Board {
   |         --------- move occurs because `board` has type `Board`, which does not implement the `Copy` trait
...
35 |     board.add_card();
   |           ---------- `board` moved due to this method call
36 |     assert_eq!(board.columns[0].len(), 5);
   |                ^^^^^^^^^^^^^^^^ value borrowed here after move

but that's because of the previous board.add_card() line, the function take ownership.

you can confirm this by commenting out the previous line, and the error will go away,

Solution

1 Change to reference

change the function to take reference only, and &mut if you need.

impl Board {
    fn add_card(&mut self){todo!()}
}

2 Return Self

change the function to take ownership and also return Self

impl Board {
    fn add_card(self)->Self{todo!()}
}

usage

let board = board.add_card();

/// you can chain method like this
let board = board
        .add_card()
        .add_card()
        .add_card()
        .add_card()
        .add_card()
        .add_card();

Upvotes: 1

Related Questions