From fa0e7fc49d4b54845d4027bf81999b6ededa13ea Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Tue, 29 Dec 2020 08:31:19 -0800 Subject: [PATCH 1/2] Add missing fmt::Debug impls to public types in regex-syntax --- regex-syntax/src/lib.rs | 1 + regex-syntax/src/utf8.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/regex-syntax/src/lib.rs b/regex-syntax/src/lib.rs index f35c9133ac..edf1b993db 100644 --- a/regex-syntax/src/lib.rs +++ b/regex-syntax/src/lib.rs @@ -155,6 +155,7 @@ The following features are available: */ #![deny(missing_docs)] +#![warn(missing_debug_implementations)] #![forbid(unsafe_code)] pub use error::{Error, Result}; diff --git a/regex-syntax/src/utf8.rs b/regex-syntax/src/utf8.rs index 489729e745..89862afb61 100644 --- a/regex-syntax/src/utf8.rs +++ b/regex-syntax/src/utf8.rs @@ -84,6 +84,7 @@ which uses it for executing automata on their term index. use std::char; use std::fmt; +use std::iter::FusedIterator; use std::slice; const MAX_UTF8_BYTES: usize = 4; @@ -295,6 +296,7 @@ impl fmt::Debug for Utf8Range { /// illustrative. In practice, you could just try to decode your byte sequence /// and compare it with the scalar value range directly. However, this is not /// always possible (for example, in a byte based automaton). +#[derive(Debug)] pub struct Utf8Sequences { range_stack: Vec, } @@ -388,6 +390,8 @@ impl Iterator for Utf8Sequences { } } +impl FusedIterator for Utf8Sequences {} + impl ScalarRange { /// split splits this range if it overlaps with a surrogate codepoint. /// From 1c609514f7020649b069896c2a6e8d5866a24b54 Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Tue, 29 Dec 2020 08:34:24 -0800 Subject: [PATCH 2/2] Add missing fmt::Debug impls to public types in regex --- src/compile.rs | 11 +++++++++++ src/exec.rs | 5 +++++ src/lib.rs | 1 + src/literal/imp.rs | 1 + src/re_builder.rs | 2 ++ src/re_bytes.rs | 8 +++++++- src/re_set.rs | 3 ++- src/re_trait.rs | 9 ++++++--- src/re_unicode.rs | 8 +++++++- 9 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/compile.rs b/src/compile.rs index cdc583c5d7..9ffd347044 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::fmt; use std::iter; use std::result; use std::sync::Arc; @@ -25,6 +26,9 @@ struct Patch { /// A compiler translates a regular expression AST to a sequence of /// instructions. The sequence of instructions represents an NFA. +// `Compiler` is only public via the `internal` module, so avoid deriving +// `Debug`. +#[allow(missing_debug_implementations)] pub struct Compiler { insts: Vec, compiled: Program, @@ -1051,6 +1055,7 @@ impl<'a, 'b> CompileClass<'a, 'b> { /// This uses similar idea to [`SparseSet`](../sparse/struct.SparseSet.html), /// except it uses hashes as original indices and then compares full keys for /// validation against `dense` array. +#[derive(Debug)] struct SuffixCache { sparse: Box<[usize]>, dense: Vec, @@ -1159,6 +1164,12 @@ impl ByteClassSet { } } +impl fmt::Debug for ByteClassSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ByteClassSet").field(&&self.0[..]).finish() + } +} + fn u32_to_usize(n: u32) -> usize { // In case usize is less than 32 bits, we need to guard against overflow. // On most platforms this compiles to nothing. diff --git a/src/exec.rs b/src/exec.rs index acca2dccb6..e1aae87088 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -30,6 +30,7 @@ use utf8::next_utf8; /// In particular, this manages the various compiled forms of a single regular /// expression and the choice of which matching engine to use to execute a /// regular expression. +#[derive(Debug)] pub struct Exec { /// All read only state. ro: Arc, @@ -49,6 +50,7 @@ pub struct ExecNoSync<'c> { } /// `ExecNoSyncStr` is like `ExecNoSync`, but matches on &str instead of &[u8]. +#[derive(Debug)] pub struct ExecNoSyncStr<'c>(ExecNoSync<'c>); /// `ExecReadOnly` comprises all read only state for a regex. Namely, all such @@ -97,6 +99,9 @@ struct ExecReadOnly { /// Facilitates the construction of an executor by exposing various knobs /// to control how a regex is executed and what kinds of resources it's /// permitted to use. +// `ExecBuilder` is only public via the `internal` module, so avoid deriving +// `Debug`. +#[allow(missing_debug_implementations)] pub struct ExecBuilder { options: RegexOptions, match_type: Option, diff --git a/src/lib.rs b/src/lib.rs index bdcebd44b3..d3dc58d66f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -616,6 +616,7 @@ another matching engine with fixed memory requirements. #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] #![cfg_attr(feature = "pattern", feature(pattern))] +#![warn(missing_debug_implementations)] #[cfg(not(feature = "std"))] compile_error!("`std` feature is currently required to build this crate"); diff --git a/src/literal/imp.rs b/src/literal/imp.rs index d6ab04dee8..e4d04ed0a9 100644 --- a/src/literal/imp.rs +++ b/src/literal/imp.rs @@ -232,6 +232,7 @@ impl Matcher { } } +#[derive(Debug)] pub enum LiteralIter<'a> { Empty, Bytes(&'a [u8]), diff --git a/src/re_builder.rs b/src/re_builder.rs index 3fef99d435..fc140f8bd0 100644 --- a/src/re_builder.rs +++ b/src/re_builder.rs @@ -47,6 +47,7 @@ macro_rules! define_builder { /// A builder can be used to configure how the regex is built, for example, by /// setting the default flags (which can be overridden in the expression /// itself) or setting various limits. + #[derive(Debug)] pub struct RegexBuilder(RegexOptions); impl RegexBuilder { @@ -244,6 +245,7 @@ macro_rules! define_set_builder { /// A builder can be used to configure how the regexes are built, for example, /// by setting the default flags (which can be overridden in the expression /// itself) or setting various limits. + #[derive(Debug)] pub struct RegexSetBuilder(RegexOptions); impl RegexSetBuilder { diff --git a/src/re_bytes.rs b/src/re_bytes.rs index a3d494ad26..a091436f14 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -691,6 +691,7 @@ impl Regex { /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the matched byte string. +#[derive(Debug)] pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSync<'r>>); impl<'r, 't> Iterator for Matches<'r, 't> { @@ -711,6 +712,7 @@ impl<'r, 't> FusedIterator for Matches<'r, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the matched byte string. +#[derive(Debug)] pub struct CaptureMatches<'r, 't>( re_trait::CaptureMatches<'t, ExecNoSync<'r>>, ); @@ -733,6 +735,7 @@ impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the byte string being split. +#[derive(Debug)] pub struct Split<'r, 't> { finder: Matches<'r, 't>, last: usize, @@ -770,6 +773,7 @@ impl<'r, 't> FusedIterator for Split<'r, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the byte string being split. +#[derive(Debug)] pub struct SplitN<'r, 't> { splits: Split<'r, 't>, n: usize, @@ -811,6 +815,7 @@ impl<'r, 't> FusedIterator for SplitN<'r, 't> {} /// whole matched region) is always unnamed. /// /// `'r` is the lifetime of the compiled regular expression. +#[derive(Clone, Debug)] pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option>); impl<'r> Iterator for CaptureNames<'r> { @@ -1078,7 +1083,7 @@ impl<'t, 'i> Index<&'i str> for Captures<'t> { /// /// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and /// the lifetime `'t` corresponds to the originally matched text. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SubCaptureMatches<'c, 't: 'c> { caps: &'c Captures<'t>, it: SubCapturesPosIter<'c>, @@ -1196,6 +1201,7 @@ where /// and performant (since capture groups don't need to be found). /// /// `'t` is the lifetime of the literal text. +#[derive(Clone, Debug)] pub struct NoExpand<'t>(pub &'t [u8]); impl<'t> Replacer for NoExpand<'t> { diff --git a/src/re_set.rs b/src/re_set.rs index 573b6e8f24..0a00229de7 100644 --- a/src/re_set.rs +++ b/src/re_set.rs @@ -320,6 +320,7 @@ impl<'a> IntoIterator for &'a SetMatches { /// This will always produces matches in ascending order of index, where the /// index corresponds to the index of the regex that matched with respect to /// its position when initially building the set. +#[derive(Debug)] pub struct SetMatchesIntoIter(iter::Enumerate>); impl Iterator for SetMatchesIntoIter { @@ -361,7 +362,7 @@ impl iter::FusedIterator for SetMatchesIntoIter {} /// This will always produces matches in ascending order of index, where the /// index corresponds to the index of the regex that matched with respect to /// its position when initially building the set. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SetMatchesIter<'a>(iter::Enumerate>); impl<'a> Iterator for SetMatchesIter<'a> { diff --git a/src/re_trait.rs b/src/re_trait.rs index 7bade98217..ea6be9c7c5 100644 --- a/src/re_trait.rs +++ b/src/re_trait.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::iter::FusedIterator; /// Slot is a single saved capture location. Note that there are two slots for @@ -53,7 +54,7 @@ impl Locations { /// Positions are byte indices in terms of the original string matched. /// /// `'c` is the lifetime of the captures. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SubCapturesPosIter<'c> { idx: usize, locs: &'c Locations, @@ -89,9 +90,9 @@ impl<'c> FusedIterator for SubCapturesPosIter<'c> {} /// somewhat reasonable. One particular thing this trait would expose would be /// the ability to start the search of a regex anywhere in a haystack, which /// isn't possible in the current public API. -pub trait RegularExpression: Sized { +pub trait RegularExpression: Sized + fmt::Debug { /// The type of the haystack. - type Text: ?Sized; + type Text: ?Sized + fmt::Debug; /// The number of capture slots in the compiled regular expression. This is /// always two times the number of capture groups (two slots per group). @@ -149,6 +150,7 @@ pub trait RegularExpression: Sized { } /// An iterator over all non-overlapping successive leftmost-first matches. +#[derive(Debug)] pub struct Matches<'t, R> where R: RegularExpression, @@ -218,6 +220,7 @@ where /// An iterator over all non-overlapping successive leftmost-first matches with /// captures. +#[derive(Debug)] pub struct CaptureMatches<'t, R>(Matches<'t, R>) where R: RegularExpression, diff --git a/src/re_unicode.rs b/src/re_unicode.rs index 5fad4d4fe9..df87c3421a 100644 --- a/src/re_unicode.rs +++ b/src/re_unicode.rs @@ -748,6 +748,7 @@ impl Regex { /// whole matched region) is always unnamed. /// /// `'r` is the lifetime of the compiled regular expression. +#[derive(Clone, Debug)] pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option>); impl<'r> Iterator for CaptureNames<'r> { @@ -777,6 +778,7 @@ impl<'r> FusedIterator for CaptureNames<'r> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the string being split. +#[derive(Debug)] pub struct Split<'r, 't> { finder: Matches<'r, 't>, last: usize, @@ -814,6 +816,7 @@ impl<'r, 't> FusedIterator for Split<'r, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the string being split. +#[derive(Debug)] pub struct SplitN<'r, 't> { splits: Split<'r, 't>, n: usize, @@ -1076,7 +1079,7 @@ impl<'t, 'i> Index<&'i str> for Captures<'t> { /// /// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and /// the lifetime `'t` corresponds to the originally matched text. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SubCaptureMatches<'c, 't: 'c> { caps: &'c Captures<'t>, it: SubCapturesPosIter<'c>, @@ -1101,6 +1104,7 @@ impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the matched string. +#[derive(Debug)] pub struct CaptureMatches<'r, 't>( re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>, ); @@ -1126,6 +1130,7 @@ impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {} /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the /// lifetime of the matched string. +#[derive(Debug)] pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSyncStr<'r>>); impl<'r, 't> Iterator for Matches<'r, 't> { @@ -1238,6 +1243,7 @@ where /// and performant (since capture groups don't need to be found). /// /// `'t` is the lifetime of the literal text. +#[derive(Clone, Debug)] pub struct NoExpand<'t>(pub &'t str); impl<'t> Replacer for NoExpand<'t> {