1extern crate bigint;
4extern crate rlp;
5#[cfg(test)]
6extern crate hexutil;
7extern crate sha3;
8
9use std::ops::BitOr;
10use bigint::H2048;
11use sha3::{Digest, Keccak256};
12use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct LogsBloom(H2048);
17
18impl From<H2048> for LogsBloom {
19 fn from(val: H2048) -> LogsBloom {
20 LogsBloom(val)
21 }
22}
23
24impl Into<H2048> for LogsBloom {
25 fn into(self) -> H2048 {
26 self.0
27 }
28}
29
30impl Encodable for LogsBloom {
31 fn rlp_append(&self, s: &mut RlpStream) {
32 self.0.rlp_append(s);
33 }
34}
35
36impl Decodable for LogsBloom {
37 fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
38 Ok(LogsBloom(H2048::decode(rlp)?))
39 }
40}
41
42impl Default for LogsBloom {
43 fn default() -> LogsBloom {
44 LogsBloom(H2048::zero())
45 }
46}
47
48impl BitOr for LogsBloom {
49 type Output = LogsBloom;
50
51 fn bitor(self, other: LogsBloom) -> LogsBloom {
52 LogsBloom(self.0 | other.0)
53 }
54}
55
56fn single_set(arr: &[u8]) -> H2048 {
57 let mut r = H2048::zero();
58 let h = Keccak256::digest(arr);
59 for i in [0usize, 2usize, 4usize].iter() {
60 let m = (((h[*i] as usize) << 8) + (h[*i + 1] as usize)) % 2048;
61 r[m / 8] = r[m / 8] | (1 << (m % 8));
62 }
63 r
64}
65
66impl LogsBloom {
67 pub fn new() -> LogsBloom {
69 LogsBloom::default()
70 }
71
72 pub fn set(&mut self, arr: &[u8]) {
74 self.0 = self.0 | single_set(arr);
75 }
76
77 pub fn check(&self, arr: &[u8]) -> bool {
79 let s = single_set(arr);
80 self.0 & s == s
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::LogsBloom;
87 use bigint::H2048;
88 use hexutil::read_hex;
89
90 #[test]
91 fn test_bloom() {
92 let mut bloom = LogsBloom::new();
93 bloom.set(&read_hex("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap());
94 assert!(bloom.check(&read_hex("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()));
95
96 let h: H2048 = bloom.into();
97 for i in [1323usize, 431usize, 1319usize].iter() {
98 let v = 1 << (i % 8);
99 assert!(h[i / 8] & v == v);
100 }
101 }
102}