Implement Extend for Vec

#1

I’ve the below structs:

use serde_derive::*;

pub type BlockHash = Vec<u8>;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Transaction {
    pub id: String,
    pub timestamp: u64,
    pub payload: String,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct Block {
    pub index: u32,
    pub timestamp: u128,
    pub hash: BlockHash,
    pub prev_block_hash: BlockHash,
    pub nonce: u64,
    pub payload: Vec<Transaction>,
}

And want to implement the below trait:

use crate::hashable::Hashable;
use crate::definition::Block;
use blockchainlib::u32_bytes;
use blockchainlib::u128_bytes;
use blockchainlib::u64_bytes;
use crate::definition;
use crate::definition::Transaction;

impl Hashable for Block {
    fn bytes (&self) -> Vec<u8> {
        let mut bytes = vec![];

        bytes.extend(&u32_bytes(&self.index));
        bytes.extend(&u128_bytes(&self.timestamp));
        bytes.extend(&self.prev_block_hash);
        bytes.extend(&u64_bytes(&self.nonce));
        bytes.extend(&self.payload);   // All the errors are due to this line!!

        bytes
    }

    fn hash(&self) -> Self {
        Block {
            index: self.index,
            timestamp: self.timestamp,
            hash: self.hash256(),
            prev_block_hash: self.prev_block_hash.to_vec(),  // Self::hash(previous_block)
            nonce: self.nonce,   // proof: 0,
            payload: self.payload.to_vec(),
        }
    }

    fn hash_check(&self) -> Vec<u8> {
        let block: Block = Block {
            index: self.index,
            timestamp: self.timestamp,
            hash: vec![],
            prev_block_hash: self.prev_block_hash.to_vec(),  // Self::hash(previous_block)
            nonce: self.nonce,   // proof: 0,
            payload: self.payload.to_vec(),
        };
        block.hash256()
    }
}

Where Hashable trait is:

use crate::definition::Block;

pub trait Hashable {
    fn bytes (&self) -> Vec<u8>; // function returns vector of bytes
                            // ^ this semicolon = no function body
    fn hash256 (&self) -> Vec<u8> {
        crypto_hash::digest(
            crypto_hash::Algorithm::SHA256,
            &self.bytes(),
        )
    }

    fn hash (&self) -> Self;
    fn hash_check (&self) -> Vec<u8>;
}

And blockchainlib is:

type BlockHash = Vec<u8>;

// Credit: https://stackoverflow.com/a/44378174/2773837
use std::time::{ SystemTime, UNIX_EPOCH };

pub fn now () -> u128 {
    let duration = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        ;

    duration.as_secs() as u128 * 1000 + duration.subsec_millis() as u128
}

pub fn u32_bytes (u: &u32) -> [u8; 4] {
    [
        (u >> 8 * 0x0) as u8,
        (u >> 8 * 0x1) as u8,
        (u >> 8 * 0x2) as u8,
        (u >> 8 * 0x3) as u8,
    ]
}

pub fn u64_bytes (u: &u64) -> [u8; 8] {
    [
        (u >> 8 * 0x0) as u8,
        (u >> 8 * 0x1) as u8,
        (u >> 8 * 0x2) as u8,
        (u >> 8 * 0x3) as u8,

        (u >> 8 * 0x4) as u8,
        (u >> 8 * 0x5) as u8,
        (u >> 8 * 0x6) as u8,
        (u >> 8 * 0x7) as u8,
    ]
}

pub fn u128_bytes (u: &u128) -> [u8; 16] {
    [
        (u >> 8 * 0x0) as u8,
        (u >> 8 * 0x1) as u8,
        (u >> 8 * 0x2) as u8,
        (u >> 8 * 0x3) as u8,

        (u >> 8 * 0x4) as u8,
        (u >> 8 * 0x5) as u8,
        (u >> 8 * 0x6) as u8,
        (u >> 8 * 0x7) as u8,

        (u >> 8 * 0x8) as u8,
        (u >> 8 * 0x9) as u8,
        (u >> 8 * 0xa) as u8,
        (u >> 8 * 0xb) as u8,

        (u >> 8 * 0xc) as u8,
        (u >> 8 * 0xd) as u8,
        (u >> 8 * 0xe) as u8,
        (u >> 8 * 0xf) as u8,
    ]
}

But I got the below error:

error[E0277]: the trait bound `std::vec::Vec<&definition::Transaction>: std::iter::Extend<&u8>` is not satisfied
  --> src/blocks_hash.rs:13:15
   |
13 |         bytes.extend(&u32_bytes(&self.index));
   |               ^^^^^^ the trait `std::iter::Extend<&u8>` is not implemented for `std::vec::Vec<&definition::Transaction>`
   |
   = help: the following implementations were found:
             <std::vec::Vec<T> as std::iter::Extend<&'a T>>
             <std::vec::Vec<T> as std::iter::Extend<T>>

error[E0277]: the trait bound `std::vec::Vec<&definition::Transaction>: std::iter::Extend<&u8>` is not satisfied
  --> src/blocks_hash.rs:14:15
   |
14 |         bytes.extend(&u128_bytes(&self.timestamp));
   |               ^^^^^^ the trait `std::iter::Extend<&u8>` is not implemented for `std::vec::Vec<&definition::Transaction>`
   |
   = help: the following implementations were found:
             <std::vec::Vec<T> as std::iter::Extend<&'a T>>
             <std::vec::Vec<T> as std::iter::Extend<T>>

error[E0277]: the trait bound `std::vec::Vec<&definition::Transaction>: std::iter::Extend<&u8>` is not satisfied
  --> src/blocks_hash.rs:15:15
   |
15 |         bytes.extend(&self.prev_block_hash);
   |               ^^^^^^ the trait `std::iter::Extend<&u8>` is not implemented for `std::vec::Vec<&definition::Transaction>`
   |
   = help: the following implementations were found:
             <std::vec::Vec<T> as std::iter::Extend<&'a T>>
             <std::vec::Vec<T> as std::iter::Extend<T>>

error[E0277]: the trait bound `std::vec::Vec<&definition::Transaction>: std::iter::Extend<&u8>` is not satisfied
  --> src/blocks_hash.rs:16:15
   |
16 |         bytes.extend(&u64_bytes(&self.nonce));
   |               ^^^^^^ the trait `std::iter::Extend<&u8>` is not implemented for `std::vec::Vec<&definition::Transaction>`
   |
   = help: the following implementations were found:
             <std::vec::Vec<T> as std::iter::Extend<&'a T>>
             <std::vec::Vec<T> as std::iter::Extend<T>>

error[E0308]: mismatched types
  --> src/blocks_hash.rs:19:9
   |
10 |     fn bytes (&self) -> Vec<u8> {
   |                         ------- expected `std::vec::Vec<u8>` because of return type
...
19 |         bytes
   |         ^^^^^ expected u8, found reference
   |
   = note: expected type `std::vec::Vec<u8>`
              found type `std::vec::Vec<&definition::Transaction>`

error: aborting due to 5 previous errors
#2

Your bytes = vec![] is of type Vec<&definitiion::Transition>.

As to know why, the most plausible explanation is that the vec! macro of the ::std lib is being shadowed by some other macro with the same name; else I can’t imagine why type inference would do such a bad job.

To get a better error message, and hopefully help you find the root of the problem, try to annotate the type of your bytes variable declaration, like this:

let mut bytes: Vec<u8> = vec![]; // This should improve the error message

There are two ways to prevent the error, if indeed it comes from shadowing:

  1. Use the full path of the vec! macro: ::std::vec![]
  2. Use Vec::new() instead of vec![]

EDIT: As @mbrubeck pointed out the problem comes from the bytes.extend(&self.payload); line; since it was the most restrictive trait-bound-wise, type inferrence had no choice but to assume that your bytes : Vec<_> was actually a Vec<&Transaction> for the program to maybe have a chance to type check (which of course it didn’t).

#3

Here bytes is a Vec<u8> and self.payload is a Vec<Transaction>:

bytes.extend(&self.payload);   // All the errors are due to this line!!

You can’t append a Vec<Transaction> to a Vec<u8>. What are you trying to do in this line?