use std::io::{self, Read, Write};
use crate::{
__impl_index,
io::{ReadFrom, TooLongError, WriteTo},
message::{InvHash, Message},
packet::Command,
var_type::VarInt,
};
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Inv {
list: Vec<InvHash>,
}
impl AsRef<[InvHash]> for Inv {
fn as_ref(&self) -> &[InvHash] {
&self.list
}
}
__impl_index!(Inv, list, InvHash);
impl Inv {
const MAX_COUNT: usize = 50000;
pub const MAX_COUNT_FIXED: usize = Self::MAX_COUNT - 1;
pub fn new(list: Vec<InvHash>) -> Result<Self, TooLongError> {
if list.len() > Self::MAX_COUNT_FIXED {
return Err(TooLongError::new(Self::MAX_COUNT_FIXED, list.len()));
}
Ok(Self { list })
}
}
impl WriteTo for Inv {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
let count: VarInt = self.list.len().into();
count.write_to(w)?;
for a in &self.list {
a.write_to(w)?
}
Ok(())
}
}
impl ReadFrom for Inv {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let count = VarInt::read_from(r)?;
if count.as_u64() > Self::MAX_COUNT as u64 {
return Err(io::Error::new(
io::ErrorKind::Other,
TooLongError::new(Self::MAX_COUNT, count.as_u64() as usize),
));
}
let mut list = Vec::<InvHash>::new();
for _ in 0..count.as_u64() {
list.push(InvHash::read_from(r)?);
}
Ok(Self { list })
}
}
impl Message for Inv {
const COMMAND: Command = Command::INV;
}
#[test]
fn test_inv_write_to() {
let inv0 = InvHash::new([0x01; 32]);
let inv1 = InvHash::new([0x23; 32]);
let inv2 = InvHash::new([0x45; 32]);
let test = Inv::new([inv0, inv1, inv2].to_vec()).unwrap();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [
3, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, ];
assert_eq!(bytes, expected.to_vec());
}
#[test]
fn test_inv_read_from() {
use std::io::Cursor;
let mut bytes = Cursor::new(
[
3, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, ]
.to_vec(),
);
let test = Inv::read_from(&mut bytes).unwrap();
let inv0 = InvHash::new([0x01; 32]);
let inv1 = InvHash::new([0x23; 32]);
let inv2 = InvHash::new([0x45; 32]);
let expected = Inv::new([inv0, inv1, inv2].to_vec()).unwrap();
assert_eq!(test, expected);
}