1pub mod store;
24
25use bytes::Bytes;
26use libp2p_core::{PeerId, Multiaddr, multihash::Multihash};
27use std::borrow::Borrow;
28use std::hash::{Hash, Hasher};
29use wasm_timer::Instant;
30
31#[derive(Clone, Debug, PartialEq, Eq, Hash)]
33pub struct Key(Bytes);
34
35impl Key {
36 pub fn new<K: AsRef<[u8]>>(key: &K) -> Self {
38 Key(Bytes::copy_from_slice(key.as_ref()))
39 }
40
41 pub fn to_vec(&self) -> Vec<u8> {
43 Vec::from(&self.0[..])
44 }
45}
46
47impl Borrow<[u8]> for Key {
48 fn borrow(&self) -> &[u8] {
49 &self.0[..]
50 }
51}
52
53impl AsRef<[u8]> for Key {
54 fn as_ref(&self) -> &[u8] {
55 &self.0[..]
56 }
57}
58
59impl From<Vec<u8>> for Key {
60 fn from(v: Vec<u8>) -> Key {
61 Key(Bytes::from(v))
62 }
63}
64
65impl From<Multihash> for Key {
66 fn from(m: Multihash) -> Key {
67 Key::from(m.to_bytes())
68 }
69}
70
71#[derive(Clone, Debug, Eq, PartialEq)]
73pub struct Record {
74 pub key: Key,
76 pub value: Vec<u8>,
78 pub publisher: Option<PeerId>,
80 pub expires: Option<Instant>,
82}
83
84impl Record {
85 pub fn new<K>(key: K, value: Vec<u8>) -> Self
87 where
88 K: Into<Key>
89 {
90 Record {
91 key: key.into(),
92 value,
93 publisher: None,
94 expires: None,
95 }
96 }
97
98 pub fn is_expired(&self, now: Instant) -> bool {
100 self.expires.map_or(false, |t| now >= t)
101 }
102}
103
104#[derive(Clone, Debug)]
111pub struct ProviderRecord {
112 pub key: Key,
114 pub provider: PeerId,
116 pub expires: Option<Instant>,
118 pub addresses: Vec<Multiaddr>
120 }
122
123impl Hash for ProviderRecord {
124 fn hash<H: Hasher>(&self, state: &mut H) {
125 self.key.hash(state);
126 self.provider.hash(state);
127 }
128}
129
130impl PartialEq for ProviderRecord {
131 fn eq(&self, other: &Self) -> bool {
132 self.key == other.key && self.provider == other.provider
133 }
134}
135
136impl Eq for ProviderRecord {}
137
138impl ProviderRecord {
139 pub fn new<K>(key: K, provider: PeerId, addresses: Vec<Multiaddr>) -> Self
141 where
142 K: Into<Key>
143 {
144 ProviderRecord {
145 key: key.into(),
146 provider,
147 expires: None,
148 addresses,
149 }
150 }
151
152 pub fn is_expired(&self, now: Instant) -> bool {
154 self.expires.map_or(false, |t| now >= t)
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use quickcheck::*;
162 use libp2p_core::multihash::Code;
163 use rand::Rng;
164 use std::time::Duration;
165
166 impl Arbitrary for Key {
167 fn arbitrary<G: Gen>(_: &mut G) -> Key {
168 let hash = rand::thread_rng().gen::<[u8; 32]>();
169 Key::from(Multihash::wrap(Code::Sha2_256.into(), &hash).unwrap())
170 }
171 }
172
173 impl Arbitrary for Record {
174 fn arbitrary<G: Gen>(g: &mut G) -> Record {
175 Record {
176 key: Key::arbitrary(g),
177 value: Vec::arbitrary(g),
178 publisher: if g.gen() { Some(PeerId::random()) } else { None },
179 expires: if g.gen() {
180 Some(Instant::now() + Duration::from_secs(g.gen_range(0, 60)))
181 } else {
182 None
183 },
184 }
185 }
186 }
187
188 impl Arbitrary for ProviderRecord {
189 fn arbitrary<G: Gen>(g: &mut G) -> ProviderRecord {
190 ProviderRecord {
191 key: Key::arbitrary(g),
192 provider: PeerId::random(),
193 expires: if g.gen() {
194 Some(Instant::now() + Duration::from_secs(g.gen_range(0, 60)))
195 } else {
196 None
197 },
198 addresses: vec![],
199 }
200 }
201 }
202}