Support derive(PartialOrd, Ord)
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 28dfae3..91a5d9d 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -15,7 +15,9 @@
Trait::Clone => expanded.extend(struct_clone(strct, span)),
Trait::Debug => expanded.extend(struct_debug(strct, span)),
Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+ Trait::Ord => expanded.extend(struct_ord(strct, span)),
Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
+ Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
}
}
@@ -52,10 +54,12 @@
traits.push(quote_spanned!(span=> ::std::cmp::Eq));
has_eq = true;
}
+ Trait::Ord => expanded.extend(enum_ord(enm, span)),
Trait::PartialEq => {
traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
has_partial_eq = true;
}
+ Trait::PartialOrd => expanded.extend(enum_partial_ord(enm, span)),
}
}
@@ -132,6 +136,54 @@
}
}
+fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
+ let ident = &strct.name.rust;
+ let fields = strct.fields.iter().map(|field| &field.ident);
+
+ quote_spanned! {span=>
+ impl ::std::cmp::Ord for #ident {
+ fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+ #(
+ match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) {
+ ::std::cmp::Ordering::Equal => {}
+ ordering => return ordering,
+ }
+ )*
+ ::std::cmp::Ordering::Equal
+ }
+ }
+ }
+}
+
+fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
+ let ident = &strct.name.rust;
+
+ let body = if derive::contains(&strct.derives, Trait::Ord) {
+ quote! {
+ ::std::option::Option::Some(::std::cmp::Ord::cmp(self, other))
+ }
+ } else {
+ let fields = strct.fields.iter().map(|field| &field.ident);
+ quote! {
+ #(
+ match ::std::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) {
+ ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {}
+ ordering => return ordering,
+ }
+ )*
+ ::std::option::Option::Some(::std::cmp::Ordering::Equal)
+ }
+ };
+
+ quote_spanned! {span=>
+ impl ::std::cmp::PartialOrd for #ident {
+ fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+ #body
+ }
+ }
+ }
+}
+
fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
let ident = &enm.name.rust;
@@ -174,3 +226,27 @@
}
}
}
+
+fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
+ let ident = &enm.name.rust;
+
+ quote_spanned! {span=>
+ impl ::std::cmp::Ord for #ident {
+ pub fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+ ::std::cmp::Ord::cmp(&self.repr, &other.repr)
+ }
+ }
+ }
+}
+
+fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream {
+ let ident = &enm.name.rust;
+
+ quote_spanned! {span=>
+ impl ::std::cmp::PartialOrd for #ident {
+ pub fn cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+ ::std::cmp::PartialOrd::cmp(&self.repr, &other.repr)
+ }
+ }
+ }
+}
diff --git a/syntax/derive.rs b/syntax/derive.rs
index d258cc7..1099967 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -12,7 +12,9 @@
Copy,
Debug,
Eq,
+ Ord,
PartialEq,
+ PartialOrd,
}
impl Derive {
@@ -22,7 +24,9 @@
"Copy" => Trait::Copy,
"Debug" => Trait::Debug,
"Eq" => Trait::Eq,
+ "Ord" => Trait::Ord,
"PartialEq" => Trait::PartialEq,
+ "PartialOrd" => Trait::PartialOrd,
_ => return None,
};
let span = ident.span();
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 021b0c3..cb0f916 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,12 +15,12 @@
#[cxx::bridge(namespace = "tests")]
pub mod ffi {
- #[derive(Clone, Debug, PartialEq, Eq)]
+ #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Shared {
z: usize,
}
- #[derive(PartialEq)]
+ #[derive(PartialEq, PartialOrd)]
struct SharedString {
msg: String,
}