Skip to content

Commit dada30c

Browse files
committed
fix: support excess comma in struct variant
1 parent ce0cbe8 commit dada30c

File tree

1 file changed

+82
-48
lines changed

1 file changed

+82
-48
lines changed

src/lib.rs

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -319,13 +319,26 @@ macro_rules! quick_error {
319319
queue [$( $tail )*]
320320
);
321321
};
322-
// Add struct enum-variant
322+
// Add struct enum-variant - e.g. { descr: &'static str }
323323
(SORT [$( $def:tt )*]
324324
items [$($( #[$imeta:meta] )*
325325
=> $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
326326
{$( $ifuncs:tt )*} )* ]
327327
buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
328-
queue [{ $( $qvar:ident: $qtyp:ty ),+ } $( $tail:tt )*]
328+
queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*]
329+
) => {
330+
quick_error!(SORT [$( $def )*]
331+
items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
332+
buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
333+
queue [$( $tail )*]);
334+
};
335+
// Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
336+
(SORT [$( $def:tt )*]
337+
items [$($( #[$imeta:meta] )*
338+
=> $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
339+
{$( $ifuncs:tt )*} )* ]
340+
buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
341+
queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*]
329342
) => {
330343
quick_error!(SORT [$( $def )*]
331344
items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
@@ -730,7 +743,7 @@ mod test {
730743

731744
quick_error! {
732745
#[derive(Debug, PartialEq)]
733-
pub enum Wrapper {
746+
pub enum TupleWrapper {
734747
/// ParseFloat Error
735748
ParseFloatError(err: ParseFloatError) {
736749
from()
@@ -743,19 +756,12 @@ mod test {
743756
display("Error: {}", descr)
744757
}
745758
/// FromUtf8 Error
746-
TupleFromUtf8Error(err: Utf8Error, source: Vec<u8>) {
759+
FromUtf8Error(err: Utf8Error, source: Vec<u8>) {
747760
cause(err)
748761
display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
749762
description("utf8 error")
750763
from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes())
751764
}
752-
// Utf8 Error
753-
StructUtf8Error{ err: Utf8Error, hint: Option<&'static str> } {
754-
cause(err)
755-
display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
756-
description("utf8 error")
757-
from(err: Utf8Error) -> { err: err, hint: None }
758-
}
759765
Discard {
760766
from(&'static str)
761767
}
@@ -766,88 +772,116 @@ mod test {
766772
}
767773

768774
#[test]
769-
fn wrapper_err() {
775+
fn tuple_wrapper_err() {
770776
let cause = "one and a half times pi".parse::<f32>().unwrap_err();
771-
let err = Wrapper::ParseFloatError(cause.clone());
777+
let err = TupleWrapper::ParseFloatError(cause.clone());
772778
assert_eq!(format!("{}", err), format!("parse float error: {}", cause));
773779
assert_eq!(format!("{:?}", err), format!("ParseFloatError({:?})", cause));
774780
assert_eq!(err.description(), cause.description());
775781
assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
776782
}
777783

778784
#[test]
779-
fn wrapper_trait_str() {
785+
fn tuple_wrapper_trait_str() {
780786
let desc = "hello";
781-
let err: &Error = &Wrapper::Other(desc);
787+
let err: &Error = &TupleWrapper::Other(desc);
782788
assert_eq!(format!("{}", err), format!("Error: {}", desc));
783789
assert_eq!(format!("{:?}", err), format!("Other({:?})", desc));
784790
assert_eq!(err.description(), desc);
785791
assert!(err.cause().is_none());
786792
}
787793

788794
#[test]
789-
fn wrapper_trait_two_fields() {
790-
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
791-
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
792-
let err: &Error = &Wrapper::TupleFromUtf8Error(cause.clone(), invalid_utf8.clone());
793-
assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
794-
assert_eq!(format!("{:?}", err), format!("TupleFromUtf8Error({:?}, {:?})", cause, invalid_utf8));
795-
assert_eq!(err.description(), "utf8 error");
796-
assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
797-
}
798-
799-
#[test]
800-
fn wrapper_struct() {
795+
fn tuple_wrapper_trait_two_fields() {
801796
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
802797
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
803-
let err: &Error = &Wrapper::StructUtf8Error{ err: cause.clone(), hint: Some("nonsense") };
798+
let err: &Error = &TupleWrapper::FromUtf8Error(cause.clone(), invalid_utf8.clone());
804799
assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
805-
assert_eq!(format!("{:?}", err), format!("StructUtf8Error {{ err: {:?}, hint: {:?} }}", cause, Some("nonsense")));
800+
assert_eq!(format!("{:?}", err), format!("FromUtf8Error({:?}, {:?})", cause, invalid_utf8));
806801
assert_eq!(err.description(), "utf8 error");
807802
assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
808803
}
809804

810805
#[test]
811-
fn wrapper_from() {
806+
fn tuple_wrapper_from() {
812807
let cause = "one and a half times pi".parse::<f32>().unwrap_err();
813-
let err = Wrapper::ParseFloatError(cause.clone());
814-
let err_from: Wrapper = From::from(cause);
808+
let err = TupleWrapper::ParseFloatError(cause.clone());
809+
let err_from: TupleWrapper = From::from(cause);
815810
assert_eq!(err_from, err);
816811
}
817812

818813
#[test]
819-
fn wrapper_custom_from() {
814+
fn tuple_wrapper_custom_from() {
820815
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
821816
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err();
822-
let err = Wrapper::TupleFromUtf8Error(cause.utf8_error().clone(), invalid_utf8);
823-
let err_from: Wrapper = From::from(cause);
824-
assert_eq!(err_from, err);
825-
}
826-
827-
#[test]
828-
fn wrapper_struct_from() {
829-
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
830-
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
831-
let err = Wrapper::StructUtf8Error{ err: cause.clone(), hint: None };
832-
let err_from: Wrapper = From::from(cause);
817+
let err = TupleWrapper::FromUtf8Error(cause.utf8_error().clone(), invalid_utf8);
818+
let err_from: TupleWrapper = From::from(cause);
833819
assert_eq!(err_from, err);
834820
}
835821

836822
#[test]
837-
fn wrapper_discard() {
838-
let err: Wrapper = From::from("hello");
823+
fn tuple_wrapper_discard() {
824+
let err: TupleWrapper = From::from("hello");
839825
assert_eq!(format!("{}", err), format!("Discard"));
840826
assert_eq!(format!("{:?}", err), format!("Discard"));
841827
assert_eq!(err.description(), "Discard");
842828
assert!(err.cause().is_none());
843829
}
844830

845831
#[test]
846-
fn wrapper_singleton() {
847-
let err: Wrapper = Wrapper::Singleton;
832+
fn tuple_wrapper_singleton() {
833+
let err: TupleWrapper = TupleWrapper::Singleton;
848834
assert_eq!(format!("{}", err), format!("Just a string"));
849835
assert_eq!(format!("{:?}", err), format!("Singleton"));
850836
assert_eq!(err.description(), "Singleton");
851837
assert!(err.cause().is_none());
852838
}
839+
840+
quick_error! {
841+
#[derive(Debug, PartialEq)]
842+
pub enum StructWrapper {
843+
// Utf8 Error
844+
Utf8Error{ err: Utf8Error, hint: Option<&'static str> } {
845+
cause(err)
846+
display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
847+
description("utf8 error")
848+
from(err: Utf8Error) -> { err: err, hint: None }
849+
}
850+
// Utf8 Error
851+
ExcessComma { descr: &'static str, } {
852+
description(descr)
853+
display("Error: {}", descr)
854+
}
855+
}
856+
}
857+
858+
#[test]
859+
fn struct_wrapper_err() {
860+
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
861+
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
862+
let err: &Error = &StructWrapper::Utf8Error{ err: cause.clone(), hint: Some("nonsense") };
863+
assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
864+
assert_eq!(format!("{:?}", err), format!("Utf8Error {{ err: {:?}, hint: {:?} }}", cause, Some("nonsense")));
865+
assert_eq!(err.description(), "utf8 error");
866+
assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
867+
}
868+
869+
#[test]
870+
fn struct_wrapper_struct_from() {
871+
let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
872+
let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
873+
let err = StructWrapper::Utf8Error{ err: cause.clone(), hint: None };
874+
let err_from: StructWrapper = From::from(cause);
875+
assert_eq!(err_from, err);
876+
}
877+
878+
#[test]
879+
fn struct_wrapper_excess_comma() {
880+
let descr = "hello";
881+
let err = StructWrapper::ExcessComma { descr: descr };
882+
assert_eq!(format!("{}", err), format!("Error: {}", descr));
883+
assert_eq!(format!("{:?}", err), format!("ExcessComma {{ descr: {:?} }}", descr));
884+
assert_eq!(err.description(), descr);
885+
assert!(err.cause().is_none());
886+
}
853887
}

0 commit comments

Comments
 (0)