use std::io::{Error, ErrorKind};
use std::iter::IntoIterator;
use crate::encodings::ID;
use crate::ByteOrder;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct SearchRange {
pub start: ID,
pub end: ID,
}
impl SearchRange {
pub fn new(start: ID, end: ID) -> Self {
Self { start, end }
}
pub fn to_bytes(&self, bo: &ByteOrder) -> Vec<u8> {
let mut result: Vec<u8> = self.start.to_bytes(bo);
result.extend(self.end.to_bytes(bo));
result
}
pub fn from_bytes(b: &[u8], bo: &ByteOrder) -> Result<Self, Error> {
let mut b = b;
let start = ID::from_bytes(b, bo)?;
b = b.get(start.byte_size()..).ok_or(ErrorKind::InvalidData)?;
let end = ID::from_bytes(b, bo)?;
Ok(SearchRange { start, end })
}
pub(crate) fn byte_size(&self) -> usize {
self.start.byte_size() + self.end.byte_size()
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct SearchRangeList(pub Vec<SearchRange>);
impl SearchRangeList {
pub fn to_bytes(&self, bo: &ByteOrder) -> Vec<u8> {
let mut result = Vec::new();
for r in &self.0 {
result.extend(r.to_bytes(bo));
}
result
}
pub fn from_bytes(b: &[u8], bo: &ByteOrder) -> Result<Self, Error> {
let mut b = b;
let mut ranges = Vec::new();
while !b.is_empty() {
let sr = SearchRange::from_bytes(b, bo)?;
b = b.get(sr.byte_size()..).ok_or(ErrorKind::InvalidData)?;
ranges.push(sr);
}
Ok(SearchRangeList(ranges))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl IntoIterator for SearchRangeList {
type Item = SearchRange;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a SearchRangeList {
type Item = &'a SearchRange;
type IntoIter = std::slice::Iter<'a, SearchRange>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn searchrange_to_bytes_len() {
let start = ID::from_str("1.2.3.4").unwrap();
let end = ID::from_str("1.2.3.8").unwrap();
let expected = start.to_bytes(&ByteOrder::LittleEndian).len()
+ end.to_bytes(&ByteOrder::LittleEndian).len();
assert_eq!(
SearchRange::new(start, end)
.to_bytes(&ByteOrder::LittleEndian)
.len(),
expected
);
}
#[test]
fn searchrange_serde() {
for bo in vec![ByteOrder::LittleEndian, ByteOrder::BigEndian] {
let start = ID::from_str("1.2.3.4").unwrap();
let end = ID::from_str("1.2.3.8").unwrap();
let expected = SearchRange::new(start, end);
let bytes = expected.to_bytes(&bo);
let got = SearchRange::from_bytes(bytes.as_slice(), &bo).unwrap();
assert_eq!(expected, got);
}
}
#[test]
fn searchrangelist_serde() {
for bo in vec![ByteOrder::LittleEndian, ByteOrder::BigEndian] {
let mut ranges = Vec::new();
let start = ID::from_str("1.2.3.4").unwrap();
let end = ID::from_str("1.2.3.8").unwrap();
let sr = SearchRange { start, end };
ranges.push(sr);
let start = ID::from_str("1.2.7.4").unwrap();
let end = ID::from_str("1.2.7.8").unwrap();
let sr = SearchRange { start, end };
ranges.push(sr);
let expected = SearchRangeList(ranges);
let bytes = expected.to_bytes(&bo);
let got = SearchRangeList::from_bytes(bytes.as_slice(), &bo).unwrap();
assert_eq!(expected, got);
}
}
#[test]
fn searchrangelist_intoiter() {
fn get(srl: &SearchRangeList) -> Vec<SearchRange> {
let mut srs = Vec::new();
for i in srl.clone().into_iter() {
srs.push(i);
}
srs
}
let expected = vec![
SearchRange::new(
ID::from_str("1.2.3").unwrap(),
ID::from_str("1.2.4").unwrap(),
),
SearchRange::new(
ID::from_str("1.4.3").unwrap(),
ID::from_str("1.4.4").unwrap(),
),
];
let vbl = SearchRangeList(expected.clone());
let got = get(&vbl);
assert_eq!(expected, got);
}
}