From 93c28b8db37f4327faace7ae7441f615c0224282 Mon Sep 17 00:00:00 2001 From: kirk Date: Sun, 10 Dec 2023 19:17:01 +0000 Subject: [PATCH] use saturating sub in proc macro --- derive/src/parse.rs | 52 +++++++++++++++++++++++++++++++--------- derive/src/serde_json.rs | 2 +- tests/parse.rs | 8 +++++++ 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/derive/src/parse.rs b/derive/src/parse.rs index e91a521..f027a75 100644 --- a/derive/src/parse.rs +++ b/derive/src/parse.rs @@ -551,8 +551,12 @@ pub fn _debug_current_token(source: &mut Peekable>(source: &mut Peekable) -> Option { - let Some (TokenTree::Punct(punct)) = source.peek() else { return None; }; - let '\'' = punct.as_char() else { return None; }; + let Some(TokenTree::Punct(punct)) = source.peek() else { + return None; + }; + let '\'' = punct.as_char() else { + return None; + }; let _ = source.next(); Some(Lifetime { @@ -592,7 +596,15 @@ fn next_type + Clone>(mut source: &mut Peekable let Some(_) = next_exact_punct(&mut source, ";") else { // This is an unbounded array, legal at end for unsized types - return Some(Type { ident: Category::Array { content_type: Box::new(next.clone()), len: None }, wraps: Some(vec![next]), ref_type: None, as_other: None }) + return Some(Type { + ident: Category::Array { + content_type: Box::new(next.clone()), + len: None, + }, + wraps: Some(vec![next]), + ref_type: None, + as_other: None, + }); }; //need to cover both the const generic and literal case @@ -662,7 +674,10 @@ fn next_type + Clone>(mut source: &mut Peekable source: &mut Peekable, ) -> Option { let mut tmp = source.clone(); - let (Some(_), Some(_)) = ( next_exact_punct(&mut tmp, "-"), next_exact_punct(&mut tmp, ">")) else { + let (Some(_), Some(_)) = ( + next_exact_punct(&mut tmp, "-"), + next_exact_punct(&mut tmp, ">"), + ) else { return None; }; drop(tmp); @@ -719,7 +734,7 @@ fn next_type + Clone>(mut source: &mut Peekable }; let true = matches!(ident.to_string().as_str(), "fn" | "FnOnce" | "FnMut" | "Fn") else { return None; - }; + }; let tok_str = source.next().unwrap().to_string(); match tok_str.as_str() { @@ -770,10 +785,10 @@ fn next_type + Clone>(mut source: &mut Peekable source: &mut Peekable, ) -> Option { let Some(TokenTree::Ident(ident)) = source.peek() else { - return None + return None; }; let true = matches!(ident.to_string().as_str(), "impl" | "dyn") else { - return None; + return None; }; match source.next().unwrap().to_string().as_str() { "impl" => { @@ -841,7 +856,14 @@ fn next_type + Clone>(mut source: &mut Peekable }; let None = next_exact_punct(source, "\'") else { - return Some(Type{ ident: Category::Lifetime { path: next_ident(source).expect("Need lifetime name") }, wraps: None, ref_type: None, as_other: None }) + return Some(Type { + ident: Category::Lifetime { + path: next_ident(source).expect("Need lifetime name"), + }, + wraps: None, + ref_type: None, + as_other: None, + }); }; let ref_type = match next_exact_punct(&mut source, "&") { @@ -909,7 +931,10 @@ fn next_type + Clone>(mut source: &mut Peekable let mut ty = next_ident(&mut source).unwrap_or_default(); while let Some(TokenTree::Punct(_)) = source.peek() { let mut tmp = source.clone(); - let (Some(_), Some(_)) = ( next_exact_punct(&mut tmp, ":"), next_exact_punct(&mut tmp, ":")) else { + let (Some(_), Some(_)) = ( + next_exact_punct(&mut tmp, ":"), + next_exact_punct(&mut tmp, ":"), + ) else { break; }; drop(tmp); @@ -1015,7 +1040,7 @@ fn next_attribute>( // all attributes, even doc-comments, starts with "#" let next_attr_punct = next_punct(&mut source); let Some("#") = next_attr_punct.as_deref() else { - return None + return None; }; let mut attr_group = next_group(&mut source) @@ -1213,7 +1238,12 @@ fn next_enum + Clone>(mut source: &mut Peekable let ty = next_type(&mut body); let Some(ty) = ty else { variants.push(Field { - ty: Type { ident: Category::None, wraps: None, ref_type: None, as_other: None }, + ty: Type { + ident: Category::None, + wraps: None, + ref_type: None, + as_other: None, + }, attributes, vis: Visibility::Public, field_name: Some(variant_name), diff --git a/derive/src/serde_json.rs b/derive/src/serde_json.rs index d6d1607..5caeda7 100644 --- a/derive/src/serde_json.rs +++ b/derive/src/serde_json.rs @@ -286,7 +286,7 @@ pub fn derive_ser_json_enum(enum_: &Enum) -> TokenStream { } => { let mut items = String::new(); let mut field_names = vec![]; - let last = contents.fields.len() - 1; + let last = contents.fields.len().saturating_sub(1); for (index, field) in contents.fields.iter().enumerate() { if let Some(name) = &&field.field_name { let proxied_field = ser_proxy_guard(name, field); diff --git a/tests/parse.rs b/tests/parse.rs index fd26909..1f75dc9 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -9,3 +9,11 @@ fn test_trailing_comma() { A } } + +// https://github.com/not-fl3/nanoserde/issues/88 +#[test] +fn test_empty_brackets() { + #[rustfmt::skip] + #[derive(SerJson, DeJson, SerBin, DeBin, SerRon, DeRon)] + enum Message { Goodbye, Greeting{} } +}