diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-07-03 13:35:38 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-07-18 17:06:52 +0200 |
commit | 3f38bd10eda9ea51130ffa40b716e7ea3364db82 (patch) | |
tree | 78683ef7df13df15c007d7dd840d7491a49db4a7 | |
parent | b00f92847d16fce7e5027ae926eb7700ee49bf5b (diff) |
openpgp: Add examples and documentation to Bitfield, make it public.
-rw-r--r-- | openpgp/NEWS | 1 | ||||
-rw-r--r-- | openpgp/src/types/bitfield.rs | 117 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 2 |
3 files changed, 117 insertions, 3 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index 01764f37..ae196d0a 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -33,6 +33,7 @@ - parse::PacketParser::start_hashing - parse::PacketParserBuilder::automatic_hashing - types::AEADAlgorithm::GCM + - types::Bitfield ** Deprecated functionality - cert::Preferences::preferred_aead_algorithms - packet::signature::SignatureBuilder::set_preferred_aead_algorithms diff --git a/openpgp/src/types/bitfield.rs b/openpgp/src/types/bitfield.rs index 313099fa..492d5875 100644 --- a/openpgp/src/types/bitfield.rs +++ b/openpgp/src/types/bitfield.rs @@ -1,6 +1,18 @@ -/// A bitfield. +//! A variable-sized set of boolean flags. + +/// A variable-sized set of boolean flags. +/// +/// This encodes flags in signature subpackets such as [`Features`] +/// and [`KeyFlags`]. The `Bitfield` grows to accommodate all bits +/// that are set, and querying a bit outside the allocated space will +/// return `false`. Note that it will not automatically shrink if +/// clearing a bit would leave trailing bytes to be zero. To do that, +/// explicitly call [`Bitfield::canonicalize`]. +/// +/// [`Features`]: crate::types::Features +/// [`KeyFlags`]: crate::types::KeyFlags #[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(crate) struct Bitfield { +pub struct Bitfield { raw: Vec<u8>, } @@ -25,6 +37,17 @@ impl AsMut<[u8]> for Bitfield { impl Bitfield { /// Returns all bits that are set starting from bit 0, the /// least-significant bit in the left-most byte. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let f = Bitfield::from(vec![0b0000_0001, 0b0000_0010]); + /// let mut i = f.iter_set(); + /// assert_eq!(i.next(), Some(0)); + /// assert_eq!(i.next(), Some(9)); + /// assert_eq!(i.next(), None); + /// ``` pub fn iter_set(&self) -> impl Iterator<Item = usize> + Send + Sync + '_ { self.raw.iter() @@ -38,12 +61,37 @@ impl Bitfield { } /// Returns the number of trailing zero bytes. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::from(vec![0b0000_0001]); + /// assert!(f.padding_bytes().is_none()); + /// f.clear(0); + /// assert_eq!(f.padding_bytes().unwrap().get(), 1); + /// f.canonicalize(); + /// assert!(f.padding_bytes().is_none()); + /// ``` pub fn padding_bytes(&self) -> Option<std::num::NonZeroUsize> { std::num::NonZeroUsize::new( self.raw.iter().rev().take_while(|b| **b == 0).count()) } /// Compares two feature sets for semantic equality. + /// + /// Returns true if both sets have the same flags set, i.e. this + /// function ignores any trailing zero bytes. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let f = Bitfield::from(vec![0b0000_0001]); + /// let g = Bitfield::from(vec![0b0000_0001, 0b0000_0000]); + /// assert!(f != g); + /// assert!(f.normalized_eq(&g)); + /// ``` pub fn normalized_eq(&self, other: &Self) -> bool { let (small, big) = if self.raw.len() < other.raw.len() { (self, other) @@ -67,16 +115,48 @@ impl Bitfield { } /// Returns a slice containing the raw values. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::default(); + /// assert_eq!(f.as_bytes(), &[]); + /// f.set(0); + /// assert_eq!(f.as_bytes(), &[0b0000_0001]); + /// ``` pub fn as_bytes(&self) -> &[u8] { &self.raw } /// Returns a mutable slice containing the raw values. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::from(vec![0b0000_0000]); + /// assert_eq!(f.get(0), false); + /// f.as_bytes_mut()[0] = 0b0000_0001; + /// assert_eq!(f.get(0), true); + /// ``` pub fn as_bytes_mut(&mut self) -> &mut [u8] { &mut self.raw } /// Returns whether the specified flag is set. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let f = Bitfield::default(); + /// assert_eq!(f.get(0), false); + /// assert_eq!(f.get(23), false); + /// + /// let f = Bitfield::from(vec![0b0000_0001]); + /// assert_eq!(f.get(0), true); + /// ``` pub fn get(&self, bit: usize) -> bool { let byte = bit / 8; @@ -89,6 +169,18 @@ impl Bitfield { } /// Canonicalize by removing any trailing zero bytes. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::from(vec![0b0000_0001]); + /// assert!(f.padding_bytes().is_none()); + /// f.clear(0); + /// assert_eq!(f.padding_bytes().unwrap().get(), 1); + /// f.canonicalize(); + /// assert!(f.padding_bytes().is_none()); + /// ``` pub fn canonicalize(&mut self) { while !self.raw.is_empty() && self.raw[self.raw.len() - 1] == 0 { self.raw.truncate(self.raw.len() - 1); @@ -96,6 +188,16 @@ impl Bitfield { } /// Sets the specified flag. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::default(); + /// assert_eq!(f.get(0), false); + /// f.set(0); + /// assert_eq!(f.get(0), true); + /// ``` pub fn set(&mut self, bit: usize) { let byte = bit / 8; while self.raw.len() <= byte { @@ -108,6 +210,17 @@ impl Bitfield { /// /// Note: This does not implicitly canonicalize the bit field. To /// do that, invoke [`Bitfield::canonicalize`]. + /// + /// # Examples + /// + /// ```rust + /// # use sequoia_openpgp::types::Bitfield; + /// let mut f = Bitfield::from(vec![0b0000_0001]); + /// assert_eq!(f.get(0), true); + /// f.clear(0); + /// assert_eq!(f.get(0), false); + /// assert_eq!(f.padding_bytes().unwrap().get(), 1); + /// ``` pub fn clear(&mut self, bit: usize) { let byte = bit / 8; if byte < self.raw.len() { diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs index 275632e2..53716fe5 100644 --- a/openpgp/src/types/mod.rs +++ b/openpgp/src/types/mod.rs @@ -53,7 +53,7 @@ use crate::Error; use crate::Result; mod bitfield; -pub(crate) use bitfield::Bitfield; +pub use bitfield::Bitfield; mod compression_level; pub use compression_level::CompressionLevel; mod features; |