Make Ord, PartialOrd opt-out in newtype_index

Also remove `step` impl if `ORD_IMPL = off`
This commit is contained in:
pierwill 2022-02-26 14:44:09 -06:00
parent 4566094913
commit c08a9a4f1d

View file

@ -10,6 +10,7 @@ mod kw {
syn::custom_keyword!(MAX); syn::custom_keyword!(MAX);
syn::custom_keyword!(ENCODABLE); syn::custom_keyword!(ENCODABLE);
syn::custom_keyword!(custom); syn::custom_keyword!(custom);
syn::custom_keyword!(ORD_IMPL);
} }
#[derive(Debug)] #[derive(Debug)]
@ -42,6 +43,7 @@ impl Parse for Newtype {
let mut max = None; let mut max = None;
let mut consts = Vec::new(); let mut consts = Vec::new();
let mut encodable = true; let mut encodable = true;
let mut ord = true;
// Parse an optional trailing comma // Parse an optional trailing comma
let try_comma = || -> Result<()> { let try_comma = || -> Result<()> {
@ -99,13 +101,20 @@ impl Parse for Newtype {
encodable = false; encodable = false;
continue; continue;
} }
if body.lookahead1().peek(kw::ORD_IMPL) {
body.parse::<kw::ORD_IMPL>()?;
body.parse::<Token![=]>()?;
body.parse::<kw::custom>()?;
ord = false;
continue;
}
// We've parsed everything that the user provided, so we're done // We've parsed everything that the user provided, so we're done
if body.is_empty() { if body.is_empty() {
break; break;
} }
// Otherwise, we are parsng a user-defined constant // Otherwise, we are parsing a user-defined constant
let const_attrs = body.call(Attribute::parse_outer)?; let const_attrs = body.call(Attribute::parse_outer)?;
body.parse::<Token![const]>()?; body.parse::<Token![const]>()?;
let const_name: Ident = body.parse()?; let const_name: Ident = body.parse()?;
@ -137,6 +146,40 @@ impl Parse for Newtype {
quote! {} quote! {}
}; };
if ord {
derive_paths.push(parse_quote!(Ord));
derive_paths.push(parse_quote!(PartialOrd));
}
let step = if ord {
quote! {
impl ::std::iter::Step for #name {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
<usize as ::std::iter::Step>::steps_between(
&Self::index(*start),
&Self::index(*end),
)
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
}
// Safety: The implementation of `Step` upholds all invariants.
unsafe impl ::std::iter::TrustedStep for #name {}
}
} else {
quote! {}
};
let debug_impl = match debug_format { let debug_impl = match debug_format {
DebugFormat::Custom => quote! {}, DebugFormat::Custom => quote! {},
DebugFormat::Format(format) => { DebugFormat::Format(format) => {
@ -152,7 +195,7 @@ impl Parse for Newtype {
Ok(Self(quote! { Ok(Self(quote! {
#(#attrs)* #(#attrs)*
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, #(#derive_paths),*)] #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)]
#[rustc_layout_scalar_valid_range_end(#max)] #[rustc_layout_scalar_valid_range_end(#max)]
#vis struct #name { #vis struct #name {
private: u32, private: u32,
@ -247,28 +290,7 @@ impl Parse for Newtype {
} }
} }
impl ::std::iter::Step for #name { #step
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
<usize as ::std::iter::Step>::steps_between(
&Self::index(*start),
&Self::index(*end),
)
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
}
// Safety: The implementation of `Step` upholds all invariants.
unsafe impl ::std::iter::TrustedStep for #name {}
impl From<#name> for u32 { impl From<#name> for u32 {
#[inline] #[inline]