lix-rs: allow exposing ord/eq operators from rust
this is a bit of a hack, but since zngur cannot handle multiple trait implementations per type yet we will have to commit to singles types. Change-Id: I60e7b96bbeaa9fb87cf43662d4a9a5d44116bf47
This commit is contained in:
@@ -2,10 +2,11 @@ use std::{error::Error, io};
|
||||
|
||||
use crate::ffi;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||
pub struct TestMultiplyAddLenArgs {
|
||||
pub a: u64,
|
||||
pub b: u64,
|
||||
pub c: Option<u64>,
|
||||
}
|
||||
|
||||
pub trait SetB {
|
||||
@@ -20,7 +21,7 @@ impl SetB for TestMultiplyAddLenArgs {
|
||||
|
||||
impl TestMultiplyAddLenArgs {
|
||||
pub fn new(a: u64, b: u64) -> Self {
|
||||
Self { a, b }
|
||||
Self { a, b, c: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,21 @@ use ::std::vec::Vec as Vec;
|
||||
|
||||
mod crate::ffi_test {
|
||||
type TestMultiplyAddLenArgs {
|
||||
#layout_conservative(size = 16, align = 8);
|
||||
#layout_conservative(size = 32, align = 8);
|
||||
wellknown_traits(Copy);
|
||||
|
||||
field a (offset = auto, type = u64);
|
||||
field b (offset = auto, type = u64);
|
||||
field c (offset = auto, type = Option<u64>);
|
||||
|
||||
fn new(u64, u64) -> TestMultiplyAddLenArgs;
|
||||
fn set_b(&mut self, u64) use SetB;
|
||||
|
||||
fn clone(&self) -> TestMultiplyAddLenArgs;
|
||||
|
||||
fn eq(&self, &TestMultiplyAddLenArgs) -> bool use ::std::cmp::PartialEq;
|
||||
fn lt(&self, &TestMultiplyAddLenArgs) -> bool use ::std::cmp::PartialOrd;
|
||||
fn le(&self, &TestMultiplyAddLenArgs) -> bool use ::std::cmp::PartialOrd;
|
||||
}
|
||||
|
||||
fn test_multiply_add_len(TestMultiplyAddLenArgs, &Vec<String>) -> (String, u64);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
///@file convenience utilities for working with the rust ffi bits
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
@@ -200,3 +202,50 @@ auto to_std(Option<Args...> r)
|
||||
namespace nix {
|
||||
using namespace rust::lix;
|
||||
}
|
||||
|
||||
namespace rust {
|
||||
template<typename Lhs, typename Rhs>
|
||||
concept HasOpLt = requires(Lhs lhs, Rhs rhs) {
|
||||
lhs.lt(rhs);
|
||||
Ref<::std::remove_cvref_t<Lhs>>{};
|
||||
Ref<::std::remove_cvref_t<Rhs>>{};
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
concept HasOpLe = requires(Lhs lhs, Rhs rhs) {
|
||||
lhs.le(rhs);
|
||||
Ref<::std::remove_cvref_t<Lhs>>{};
|
||||
Ref<::std::remove_cvref_t<Rhs>>{};
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
concept HasOpEq = requires(Lhs lhs, Rhs rhs) {
|
||||
lhs.eq(rhs);
|
||||
Ref<::std::remove_cvref_t<Lhs>>{};
|
||||
Ref<::std::remove_cvref_t<Rhs>>{};
|
||||
};
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define LIX_DECLARE_ORD_OPS(ns) \
|
||||
namespace ns { \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpLt<Lhs, Rhs> \
|
||||
bool operator<(const Lhs & lhs, const Rhs & rhs) { return bool(lhs.lt(rhs)); } \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpLe<Lhs, Rhs> \
|
||||
bool operator<=(const Lhs & lhs, const Rhs & rhs) { return bool(lhs.le(rhs)); } \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpLt<Lhs, Rhs> \
|
||||
bool operator>(const Lhs & lhs, const Rhs & rhs) { return bool(rhs.lt(lhs)); } \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpLe<Lhs, Rhs> \
|
||||
bool operator>=(const Lhs & lhs, const Rhs & rhs) { return bool(rhs.le(lhs)); } \
|
||||
}
|
||||
#define LIX_DECLARE_EQ_OPS(ns) \
|
||||
namespace ns { \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpEq<Lhs, Rhs> \
|
||||
bool operator==(const Lhs & lhs, const Rhs & rhs) { return bool(lhs.eq(rhs)); } \
|
||||
template<typename Lhs, typename Rhs> requires ::rust::HasOpEq<Lhs, Rhs> \
|
||||
bool operator!=(const Lhs & lhs, const Rhs & rhs) { return !bool(lhs.eq(rhs)); } \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
LIX_DECLARE_ORD_OPS(rust::lix::ffi_test)
|
||||
LIX_DECLARE_EQ_OPS(rust::lix::ffi_test)
|
||||
|
||||
@@ -87,4 +87,39 @@ TEST(rustSupport, testResultFromCxx)
|
||||
result = test_exceptions(make_box_fn([] {}));
|
||||
ASSERT_EQ(to_std_string(result), "");
|
||||
}
|
||||
|
||||
TEST(rustSupport, testOperators)
|
||||
{
|
||||
using rust::lix::ffi_test::TestMultiplyAddLenArgs;
|
||||
|
||||
auto args1 = TestMultiplyAddLenArgs::new_(1, 2);
|
||||
auto args2 = TestMultiplyAddLenArgs::new_(1, 3);
|
||||
|
||||
ASSERT_LT(args1, args2);
|
||||
ASSERT_LE(args1, args1);
|
||||
ASSERT_LE(args1, args2);
|
||||
|
||||
ASSERT_GT(args2, args1);
|
||||
ASSERT_GE(args1, args1);
|
||||
ASSERT_GE(args2, args1);
|
||||
|
||||
ASSERT_EQ(args1, args1);
|
||||
ASSERT_NE(args1, args2);
|
||||
|
||||
std::map<TestMultiplyAddLenArgs, int> map{{args2, 2}, {args1, 1}};
|
||||
|
||||
ASSERT_EQ(map.begin()->first, args1);
|
||||
ASSERT_EQ(map.begin()->second, 1);
|
||||
ASSERT_EQ(map.rbegin()->first, args2);
|
||||
ASSERT_EQ(map.rbegin()->second, 2);
|
||||
|
||||
std::set<TestMultiplyAddLenArgs> set;
|
||||
|
||||
set.emplace(args1);
|
||||
set.emplace(args1);
|
||||
set.emplace(args1);
|
||||
set.emplace(args1);
|
||||
|
||||
ASSERT_EQ(set.size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user