1use std::collections::HashMap;
10use std::hash::Hash;
11use std::io::Cursor;
12use std::mem::size_of;
13
14use bytepack::{Packed, Unpacker};
15
16use Match;
17
18pub trait HashMatchKey: Packed + Hash + Eq + Copy {}
25
26impl HashMatchKey for u8 {}
27impl HashMatchKey for [u8;2] {}
28impl HashMatchKey for [u8;3] {}
29impl HashMatchKey for [u8;4] {}
30impl HashMatchKey for [u8;5] {}
31impl HashMatchKey for [u8;6] {}
32impl HashMatchKey for [u8;7] {}
33impl HashMatchKey for [u8;8] {}
34impl HashMatchKey for u16 {}
35impl HashMatchKey for [u16;2] {}
36impl HashMatchKey for [u16;3] {}
37impl HashMatchKey for [u16;4] {}
38impl HashMatchKey for [u16;5] {}
39impl HashMatchKey for [u16;6] {}
40impl HashMatchKey for [u16;7] {}
41impl HashMatchKey for [u16;8] {}
42impl HashMatchKey for u32 {}
43impl HashMatchKey for [u32;2] {}
44impl HashMatchKey for [u32;3] {}
45impl HashMatchKey for [u32;4] {}
46impl HashMatchKey for [u32;5] {}
47impl HashMatchKey for [u32;6] {}
48impl HashMatchKey for [u32;7] {}
49impl HashMatchKey for [u32;8] {}
50impl HashMatchKey for u64 {}
51impl HashMatchKey for [u64;2] {}
52impl HashMatchKey for [u64;3] {}
53impl HashMatchKey for [u64;4] {}
54impl HashMatchKey for [u64;5] {}
55impl HashMatchKey for [u64;6] {}
56impl HashMatchKey for [u64;7] {}
57impl HashMatchKey for [u64;8] {}
58
59fn build_map<T: HashMatchKey>(c: &mut Cursor<&[u8]>) -> HashMap<T,Vec<usize>> {
60 let size = c.get_ref().len() - size_of::<T>() + 1;
61 let mut map = HashMap::<T, Vec<usize>>::with_capacity(size);
62 for i in 0..size {
63 c.set_position(i as u64);
64 let v = c.unpack::<T>().unwrap();
65 if !map.contains_key(&v) {
66 map.insert(v, Vec::<usize>::new());
67 }
68 map.get_mut(&v).unwrap().push(i);
69 }
70 return map;
71}
72
73pub struct HashMatchIterator<'a, T: HashMatchKey> {
88 first: Cursor<&'a [u8]>,
89 second: Cursor<&'a [u8]>,
90 second_len: usize,
91 i: usize,
92 j: usize,
93 map: HashMap<T,Vec<usize>>,
94 matched: HashMap<isize, usize>
95}
96
97impl<'a, T: HashMatchKey> HashMatchIterator<'a, T> {
98 pub fn new(first: &'a [u8], second: &'a [u8]) -> HashMatchIterator<'a, T> {
100 let second_len = second.len() - size_of::<T>() + 1;
101 let mut first_cursor = Cursor::new(first);
102 let second_cursor = Cursor::new(second);
103 let map = build_map(&mut first_cursor);
104 HashMatchIterator {
105 first: first_cursor,
106 second: second_cursor,
107 second_len: second_len,
108 i: 0,
109 j: 0,
110 map: map,
111 matched: HashMap::new()
112 }
113 }
114 pub fn reset(&mut self) {
117 self.i = 0;
118 self.j = 0;
119 self.matched.clear();
120 }
121}
122
123impl<'a, T: HashMatchKey> Iterator for HashMatchIterator<'a, T> {
124 type Item = Match;
125 fn next(&mut self) -> Option<Match> {
126 while self.j < self.second_len {
127 self.second.set_position(self.j as u64);
128 let v = self.second.unpack::<T>().unwrap();
129 if let Some(positions) = self.map.get(&v) {
130 while self.i < positions.len() {
131 let first_pos = positions[self.i];
132 self.i += 1;
133 let delta = first_pos as isize - self.j as isize;
135 if !(self.matched.contains_key(&delta) && self.matched.get(&delta).unwrap() >= &self.j) {
136 let first_data = self.first.get_ref();
137 let second_data = self.second.get_ref();
138 let mut idx = 0;
140 while (first_pos + idx) < first_data.len() &&
141 (self.j + idx) < second_data.len() &&
142 first_data[first_pos + idx] == second_data[self.j + idx] {
143 idx += 1;
144 }
145 self.matched.insert(delta, self.j + idx);
147 return Some(Match::new(first_pos, self.j, idx));
148 }
149 }
150 }
151 self.j += 1;
152 self.i = 0;
153 }
154 return None;
155 }
156}