#![allow(unused_assignments)]
use cbor::CborTagEncode;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use types;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct FindGroupResponse {
pub target_id : types::DhtId,
pub group : Vec<types::PublicPmid>
}
impl FindGroupResponse {
pub fn generate_random() -> FindGroupResponse {
let mut vec: Vec<types::PublicPmid> = Vec::with_capacity(99);
for i in 0..99 {
vec.push(types::PublicPmid::generate_random());
}
FindGroupResponse {
target_id: types::DhtId::generate_random(),
group: vec,
}
}
pub fn merge(&self, others : &Vec<FindGroupResponse>) -> Option<FindGroupResponse> {
let mut frequency_count : Vec<(types::PublicPmid, usize)>
= Vec::with_capacity(2 * types::GROUP_SIZE as usize);
for public_pmid in &self.group {
let mut new_public_pmid : bool = false;
match frequency_count.iter_mut()
.find(|ref mut count| count.0.public_key == public_pmid.public_key) {
Some(count) => count.1 += 1,
None => new_public_pmid = true
};
if new_public_pmid { frequency_count.push((public_pmid.clone(), 1)); };
}
for other in others {
if other.target_id != self.target_id { return None; }
for public_pmid in &other.group {
let mut new_public_pmid : bool = false;
match frequency_count.iter_mut()
.find(|ref mut count| count.0.public_key == public_pmid.public_key) {
Some(count) => count.1 += 1,
None => new_public_pmid = true
};
if new_public_pmid { frequency_count.push((public_pmid.clone(), 1)); };
}
}
frequency_count.sort_by(|a, b| b.1.cmp(&a.1));
let mut merged_group : Vec<types::PublicPmid>
= Vec::with_capacity(types::GROUP_SIZE as usize);
for public_pmid_count in frequency_count {
if merged_group.len() < types::GROUP_SIZE as usize {
assert!(public_pmid_count.1 <= types::GROUP_SIZE as usize);
merged_group.push(public_pmid_count.0);
} else {
break; }
}
assert_eq!(merged_group.len(), types::GROUP_SIZE as usize);
Some(FindGroupResponse{target_id : self.target_id.clone(),
group : merged_group})
}
}
impl Encodable for FindGroupResponse {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_001, &(&self.target_id, &self.group)).encode(e)
}
}
impl Decodable for FindGroupResponse {
fn decode<D: Decoder>(d: &mut D)->Result<FindGroupResponse, D::Error> {
try!(d.read_u64());
let (target_id, group) = try!(Decodable::decode(d));
Ok(FindGroupResponse { target_id: target_id, group: group})
}
}
#[cfg(test)]
mod test {
use super::*;
use cbor;
#[test]
fn find_group_response_serialisation() {
let obj_before = FindGroupResponse::generate_random();
let mut e = cbor::Encoder::from_memory();
e.encode(&[&obj_before]).unwrap();
let mut d = cbor::Decoder::from_bytes(e.as_bytes());
let obj_after: FindGroupResponse = d.decode().next().unwrap().unwrap();
assert_eq!(obj_before, obj_after);
}
}