use routing_table::Xorable;
use rust_sodium::crypto::hash::sha256;
use std::fmt::Write;
use std::iter;
use xor_name::XorName;
pub fn format_binary_array<V: AsRef<[u8]>>(input: V) -> String {
let input_ref = input.as_ref();
if input_ref.len() <= 6 {
let mut ret = String::new();
for byte in input_ref.iter() {
unwrap!(write!(ret, "{:02x}", byte));
}
return ret;
}
format!("{:02x}{:02x}{:02x}..{:02x}{:02x}{:02x}",
input_ref[0],
input_ref[1],
input_ref[2],
input_ref[input_ref.len() - 3],
input_ref[input_ref.len() - 2],
input_ref[input_ref.len() - 1])
}
pub fn calculate_relocated_name(mut close_nodes: Vec<XorName>, original_name: &XorName) -> XorName {
close_nodes.sort_by(|a, b| original_name.cmp_distance(a, b));
let combined: Vec<u8> = iter::once(original_name)
.chain(close_nodes.iter().take(2))
.flat_map(|close_node| close_node.0.into_iter())
.cloned()
.collect();
XorName(sha256::hash(&combined).0)
}
#[cfg(test)]
mod tests {
use rand;
use routing_table::Xorable;
use rust_sodium::crypto::hash::sha256;
use xor_name::XorName;
#[test]
fn calculate_relocated_name() {
let min_section_size = 8;
let original_name: XorName = rand::random();
let mut close_nodes_one_entry: Vec<XorName> = Vec::new();
close_nodes_one_entry.push(rand::random());
let actual_relocated_name_one_entry =
super::calculate_relocated_name(close_nodes_one_entry.clone(), &original_name);
assert_ne!(original_name, actual_relocated_name_one_entry);
let mut combined_one_node_vec: Vec<XorName> = Vec::new();
combined_one_node_vec.push(original_name);
combined_one_node_vec.push(close_nodes_one_entry[0]);
let mut combined_one_node: Vec<u8> = Vec::new();
for node_id in combined_one_node_vec {
for i in &node_id.0 {
combined_one_node.push(*i);
}
}
let expected_relocated_name_one_node = XorName(sha256::hash(&combined_one_node).0);
assert_eq!(actual_relocated_name_one_entry,
expected_relocated_name_one_node);
let mut close_nodes: Vec<XorName> = Vec::new();
for _ in 0..min_section_size {
close_nodes.push(rand::random());
}
let actual_relocated_name = super::calculate_relocated_name(close_nodes.clone(),
&original_name);
assert_ne!(original_name, actual_relocated_name);
close_nodes.sort_by(|a, b| original_name.cmp_distance(a, b));
let first_closest = close_nodes[0];
let second_closest = close_nodes[1];
let mut combined: Vec<u8> = Vec::new();
for i in &original_name.0 {
combined.push(*i);
}
for i in &first_closest.0 {
combined.push(*i);
}
for i in &second_closest.0 {
combined.push(*i);
}
let expected_relocated_name = XorName(sha256::hash(&combined).0);
assert_eq!(expected_relocated_name, actual_relocated_name);
let mut invalid_combined: Vec<u8> = Vec::new();
for i in &first_closest.0 {
invalid_combined.push(*i);
}
for i in &second_closest.0 {
invalid_combined.push(*i);
}
for i in &original_name.0 {
invalid_combined.push(*i);
}
let invalid_relocated_name = XorName(sha256::hash(&invalid_combined).0);
assert_ne!(invalid_relocated_name, actual_relocated_name);
}
}