@@ -23,10 +23,10 @@ pub struct Trailers<'a> {
2323#[ derive( PartialEq , Eq , Debug , Hash , Ord , PartialOrd , Clone , Copy ) ]
2424#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
2525pub struct TrailerRef < ' a > {
26- /// The name of the trailer, like "Signed-off-by", up to the separator ": "
26+ /// The name of the trailer, like "Signed-off-by", up to the separator `: `.
2727 #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
2828 pub token : & ' a BStr ,
29- /// The value right after the separator ": " , with leading and trailing whitespace trimmed.
29+ /// The value right after the separator `: ` , with leading and trailing whitespace trimmed.
3030 /// Note that multi-line values aren't currently supported.
3131 pub value : & ' a BStr ,
3232}
@@ -93,7 +93,7 @@ impl<'a> BodyRef<'a> {
9393 self . body_without_trailer
9494 }
9595
96- /// Return an iterator over the trailers parsed from the last paragraph of the body. May be empty.
96+ /// Return an iterator over the trailers parsed from the last paragraph of the body. Maybe empty.
9797 pub fn trailers ( & self ) -> Trailers < ' a > {
9898 Trailers {
9999 cursor : self . start_of_trailer ,
@@ -114,6 +114,69 @@ impl Deref for BodyRef<'_> {
114114 self . body_without_trailer
115115 }
116116}
117+
118+ /// Convenience methods
119+ impl TrailerRef < ' _ > {
120+ /// Check if this trailer is a `Signed-off-by` trailer (case-insensitive).
121+ pub fn is_signed_off_by ( & self ) -> bool {
122+ self . token . eq_ignore_ascii_case ( b"Signed-off-by" )
123+ }
124+
125+ /// Check if this trailer is a `Co-authored-by` trailer (case-insensitive).
126+ pub fn is_co_authored_by ( & self ) -> bool {
127+ self . token . eq_ignore_ascii_case ( b"Co-authored-by" )
128+ }
129+
130+ /// Check if this trailer is an `Acked-by` trailer (case-insensitive).
131+ pub fn is_acked_by ( & self ) -> bool {
132+ self . token . eq_ignore_ascii_case ( b"Acked-by" )
133+ }
134+
135+ /// Check if this trailer is a `Reviewed-by` trailer (case-insensitive).
136+ pub fn is_reviewed_by ( & self ) -> bool {
137+ self . token . eq_ignore_ascii_case ( b"Reviewed-by" )
138+ }
139+
140+ /// Check if this trailer is a `Tested-by` trailer (case-insensitive).
141+ pub fn is_tested_by ( & self ) -> bool {
142+ self . token . eq_ignore_ascii_case ( b"Tested-by" )
143+ }
144+
145+ /// Check if this trailer represents any kind of authorship or attribution
146+ /// (`Signed-off-by`, `Co-authored-by`, etc.).
147+ pub fn is_attribution ( & self ) -> bool {
148+ self . is_signed_off_by ( )
149+ || self . is_co_authored_by ( )
150+ || self . is_acked_by ( )
151+ || self . is_reviewed_by ( )
152+ || self . is_tested_by ( )
153+ }
154+ }
155+
156+ /// Convenience methods
157+ impl < ' a > Trailers < ' a > {
158+ /// Filter trailers to only include `Signed-off-by` entries.
159+ pub fn signed_off_by ( self ) -> impl Iterator < Item = TrailerRef < ' a > > {
160+ self . filter ( TrailerRef :: is_signed_off_by)
161+ }
162+
163+ /// Filter trailers to only include `Co-authored-by` entries.
164+ pub fn co_authored_by ( self ) -> impl Iterator < Item = TrailerRef < ' a > > {
165+ self . filter ( TrailerRef :: is_co_authored_by)
166+ }
167+
168+ /// Filter trailers to only include attribution-related entries.
169+ /// (`Signed-off-by`, `Co-authored-by`, `Acked-by`, `Reviewed-by`, `Tested-by`).
170+ pub fn attributions ( self ) -> impl Iterator < Item = TrailerRef < ' a > > {
171+ self . filter ( TrailerRef :: is_attribution)
172+ }
173+
174+ /// Filter trailers to only include authors from `Signed-off-by` and `Co-authored-by` entries.
175+ pub fn authors ( self ) -> impl Iterator < Item = TrailerRef < ' a > > {
176+ self . filter ( |trailer| trailer. is_signed_off_by ( ) || trailer. is_co_authored_by ( ) )
177+ }
178+ }
179+
117180#[ cfg( test) ]
118181mod test_parse_trailer {
119182 use super :: * ;
0 commit comments