summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-07-03 13:35:38 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-07-18 17:06:52 +0200
commit3f38bd10eda9ea51130ffa40b716e7ea3364db82 (patch)
tree78683ef7df13df15c007d7dd840d7491a49db4a7
parentb00f92847d16fce7e5027ae926eb7700ee49bf5b (diff)
openpgp: Add examples and documentation to Bitfield, make it public.
-rw-r--r--openpgp/NEWS1
-rw-r--r--openpgp/src/types/bitfield.rs117
-rw-r--r--openpgp/src/types/mod.rs2
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;