//! Misc helper functions and types for use in parsing network documents use derive_deftly::define_derive_deftly; pub(crate) mod str; pub mod batching_split_before; use std::iter::Peekable; define_derive_deftly! { /// Implement `AsMut` /// /// For Reasons, Rust does not have a blanket: /// /// ```rust,ignore /// impl AsMut for T { .. } /// ``` /// /// This derive macro expands to the obvious and trivial implementation, /// for the type that it's applied to. // // TODO move this somewhere lower in the stack, eg tor-basic-utils export AsMutSelf expect items: impl<$tgens> ::std::convert::AsMut for $ttype where $twheres { fn as_mut(&mut self) -> &mut Self { self } } } /// An iterator with a `.peek()` method /// /// We make this a trait to avoid entangling all the types with `Peekable`. /// Ideally we would do this with `Itertools::PeekingNext` /// but that was not implemented for `&mut PeekingNext` /// when we wrote this code, /// and we need that because we use a lot of `&mut NetdocReader`. /// /// /// TODO: As of itertools 0.11.0, `PeekingNext` _is_ implemented for /// `&'a mut I where I: PeekingNext`, so we can remove this type some time. /// /// # **UNSTABLE** /// /// This type is UNSTABLE and not part of the semver guarantees. /// You'll only see it if you ran rustdoc with `--document-private-items`. // This is needed because this is a trait bound for batching_split_before. #[doc(hidden)] pub trait PeekableIterator: Iterator { /// Inspect the next item, if there is one fn peek(&mut self) -> Option<&Self::Item>; } impl PeekableIterator for Peekable { fn peek(&mut self) -> Option<&Self::Item> { self.peek() } } impl PeekableIterator for &mut I { fn peek(&mut self) -> Option<&Self::Item> { ::peek(*self) } } /// A Private module for declaring a "sealed" trait. pub(crate) mod private { /// A non-exported trait, used to prevent others from implementing a trait. /// /// For more information on this pattern, see [the Rust API /// guidelines](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-sealed). #[expect(dead_code, unreachable_pub)] // TODO keep this Sealed trait in case we want it again? pub trait Sealed {} } #[cfg(test)] #[allow(unused)] fn test_as_mut_compiles() { use derive_deftly::Deftly; #[derive(Deftly)] #[derive_deftly(AsMutSelf)] struct S where Option: Clone, { t: T, } let _: &mut S<()> = S { t: () }.as_mut(); } /// Define `DirectorySignatureHashAlgo`, for `directory-signature` items /// /// This macro exists to avoid clone-and-hack between poc and prod code. /// /// It is difficult for either of those modules to use the other's definition, /// because they have different stability, different cfg gating, /// and want to derive deftly differently. /// /// tl;dr: defining this type in doc/netstatus.rs would mean /// the poc derived structs would end up in the prod module; /// defining it in poc puts it behind the `incomplete` feature gate. // // TODO DIRAUTH after poc abolished, turn back into a normal struct DirectorySignatureHashAlgo macro_rules! define_directory_signature_hash_algo { { $( $attrs:tt )* } => { /// `directory-signature` hash algorithm argument #[derive(Clone, Copy, Debug, Eq, PartialEq, strum::EnumString, Deftly)] $($attrs)* #[non_exhaustive] #[strum(serialize_all = "snake_case")] pub enum DirectorySignatureHashAlgo { /// SHA-1 #[deftly(hash_len = "20")] Sha1, /// SHA-256 #[deftly(hash_len = "32")] Sha256, } } }