|
33 | 33 | //! assert_eq!(&bytes[..], &[0xBF, 0x0C, 0x6B, 0xBD]); |
34 | 34 | //! ``` |
35 | 35 |
|
36 | | -use core::convert::From; |
37 | | -use core::{fmt, ops}; |
| 36 | +use core::fmt; |
38 | 37 |
|
39 | 38 | use hashes::Hash; |
40 | 39 |
|
41 | 40 | use crate::consensus::encode::{self, Decodable, Encodable}; |
42 | | -use crate::{BlockHash, io}; |
43 | | - |
44 | | -// Re-export NODE_HEADERS_COMPRESSED for convenience |
45 | | -pub const NODE_HEADERS_COMPRESSED: ServiceFlags = ServiceFlags::NODE_HEADERS_COMPRESSED; |
| 41 | +use crate::{BlockHash, VarInt, io}; |
46 | 42 |
|
47 | 43 | /// Version of the protocol as appearing in network message headers |
48 | 44 | /// This constant is used to signal to other peers which features you support. |
@@ -231,30 +227,44 @@ impl ServiceFlags { |
231 | 227 | // NOTE: When adding new flags, remember to update the Display impl accordingly. |
232 | 228 |
|
233 | 229 | /// Add [ServiceFlags] together. |
234 | | - /// |
235 | | - /// Returns itself. |
236 | | - pub fn add(&mut self, other: ServiceFlags) -> ServiceFlags { |
| 230 | + pub fn add(&mut self, other: ServiceFlags) { |
237 | 231 | self.0 |= other.0; |
238 | | - *self |
239 | 232 | } |
240 | 233 |
|
241 | 234 | /// Remove [ServiceFlags] from this. |
242 | | - /// |
243 | | - /// Returns itself. |
244 | | - pub fn remove(&mut self, other: ServiceFlags) -> ServiceFlags { |
| 235 | + pub fn remove(&mut self, other: ServiceFlags) { |
245 | 236 | self.0 ^= other.0; |
246 | | - *self |
247 | 237 | } |
248 | 238 |
|
249 | 239 | /// Check whether [ServiceFlags] are included in this one. |
250 | | - pub fn has(self, flags: ServiceFlags) -> bool { |
| 240 | + pub fn has(&self, flags: ServiceFlags) -> bool { |
251 | 241 | (self.0 | flags.0) == self.0 |
252 | 242 | } |
253 | 243 |
|
254 | 244 | /// Get the integer representation of this [ServiceFlags]. |
255 | | - pub fn as_u64(self) -> u64 { |
| 245 | + pub fn as_u64(&self) -> u64 { |
256 | 246 | self.0 |
257 | 247 | } |
| 248 | + |
| 249 | + // This struct is weird in the dash protocol, sometime services are encoded as u64 |
| 250 | + // and sometimes as a VarInt. While the Encodable/Decodable encodes and decodes the u64 |
| 251 | + // as usual, this methods use VarInt to satisfy the protocol |
| 252 | + |
| 253 | + #[inline] |
| 254 | + pub fn consensus_encode_as_var_int<W: io::Write + ?Sized>( |
| 255 | + &self, |
| 256 | + w: &mut W, |
| 257 | + ) -> Result<usize, io::Error> { |
| 258 | + self.0.consensus_encode(w) |
| 259 | + } |
| 260 | + |
| 261 | + #[inline] |
| 262 | + pub fn consensus_decode_from_var_int<R: io::Read + ?Sized>( |
| 263 | + r: &mut R, |
| 264 | + ) -> Result<Self, encode::Error> { |
| 265 | + let services = VarInt::consensus_decode(r)?; |
| 266 | + Ok(ServiceFlags(services.0)) |
| 267 | + } |
258 | 268 | } |
259 | 269 |
|
260 | 270 | impl fmt::LowerHex for ServiceFlags { |
@@ -307,54 +317,20 @@ impl fmt::Display for ServiceFlags { |
307 | 317 | } |
308 | 318 | } |
309 | 319 |
|
310 | | -impl From<u64> for ServiceFlags { |
311 | | - fn from(f: u64) -> Self { |
312 | | - ServiceFlags(f) |
313 | | - } |
314 | | -} |
315 | | - |
316 | | -impl From<ServiceFlags> for u64 { |
317 | | - fn from(val: ServiceFlags) -> Self { |
318 | | - val.0 |
319 | | - } |
320 | | -} |
321 | | - |
322 | | -impl ops::BitOr for ServiceFlags { |
323 | | - type Output = Self; |
324 | | - |
325 | | - fn bitor(mut self, rhs: Self) -> Self { |
326 | | - self.add(rhs) |
327 | | - } |
328 | | -} |
329 | | - |
330 | | -impl ops::BitOrAssign for ServiceFlags { |
331 | | - fn bitor_assign(&mut self, rhs: Self) { |
332 | | - self.add(rhs); |
333 | | - } |
334 | | -} |
335 | | - |
336 | | -impl ops::BitXor for ServiceFlags { |
337 | | - type Output = Self; |
338 | | - |
339 | | - fn bitxor(mut self, rhs: Self) -> Self { |
340 | | - self.remove(rhs) |
341 | | - } |
342 | | -} |
343 | | - |
344 | | -impl ops::BitXorAssign for ServiceFlags { |
345 | | - fn bitxor_assign(&mut self, rhs: Self) { |
346 | | - self.remove(rhs); |
347 | | - } |
348 | | -} |
349 | | - |
350 | 320 | impl Encodable for ServiceFlags { |
| 321 | + /// Encodes the service flags as a u64, not a VarInt. Services are usually encoded as a u64 |
| 322 | + /// but there are some messages that encode them as a VarInt instead. For those use the |
| 323 | + /// specialized method `consensus_encode_as_var_int`. |
351 | 324 | #[inline] |
352 | 325 | fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> { |
353 | 326 | self.0.consensus_encode(w) |
354 | 327 | } |
355 | 328 | } |
356 | 329 |
|
357 | 330 | impl Decodable for ServiceFlags { |
| 331 | + /// Decodes the service flags as a u64, not a VarInt. Services are usually decoded as a u64 |
| 332 | + /// but there are some messages that decode them as a VarInt instead. For those use the |
| 333 | + /// specialized method `consensus_decode_as_var_int`. |
358 | 334 | #[inline] |
359 | 335 | fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> { |
360 | 336 | Ok(ServiceFlags(Decodable::consensus_decode(r)?)) |
@@ -434,27 +410,28 @@ mod tests { |
434 | 410 | assert!(!flags.has(*f)); |
435 | 411 | } |
436 | 412 |
|
437 | | - flags |= ServiceFlags::WITNESS; |
| 413 | + flags.add(ServiceFlags::WITNESS); |
438 | 414 | assert_eq!(flags, ServiceFlags::WITNESS); |
439 | 415 |
|
440 | | - let mut flags2 = flags | ServiceFlags::GETUTXO; |
| 416 | + flags.add(ServiceFlags::GETUTXO); |
441 | 417 | for f in all.iter() { |
442 | | - assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO); |
| 418 | + assert_eq!(flags.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO); |
443 | 419 | } |
444 | 420 |
|
445 | | - flags2 ^= ServiceFlags::WITNESS; |
446 | | - assert_eq!(flags2, ServiceFlags::GETUTXO); |
| 421 | + flags.remove(ServiceFlags::WITNESS); |
| 422 | + assert_eq!(flags, ServiceFlags::GETUTXO); |
447 | 423 |
|
448 | | - flags2 |= ServiceFlags::COMPACT_FILTERS; |
449 | | - flags2 ^= ServiceFlags::GETUTXO; |
450 | | - assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS); |
| 424 | + flags.add(ServiceFlags::COMPACT_FILTERS); |
| 425 | + flags.remove(ServiceFlags::GETUTXO); |
| 426 | + assert_eq!(flags, ServiceFlags::COMPACT_FILTERS); |
451 | 427 |
|
452 | 428 | // Test formatting. |
453 | 429 | assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string()); |
454 | 430 | assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string()); |
455 | | - let flag = ServiceFlags::WITNESS | ServiceFlags::BLOOM | ServiceFlags::NETWORK; |
456 | | - assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flag.to_string()); |
457 | | - let flag = ServiceFlags::WITNESS | 0xf0.into(); |
458 | | - assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string()); |
| 431 | + |
| 432 | + let mut flags = ServiceFlags::WITNESS; |
| 433 | + flags.add(ServiceFlags::BLOOM); |
| 434 | + flags.add(ServiceFlags::NETWORK); |
| 435 | + assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flags.to_string()); |
459 | 436 | } |
460 | 437 | } |
0 commit comments