23
23
*/
24
24
25
25
#include < graphene/protocol/restriction_predicate.hpp>
26
+ #include < graphene/protocol/fee_schedule.hpp>
26
27
27
28
#include < fc/exception/exception.hpp>
28
29
@@ -50,7 +51,8 @@ template<typename T> constexpr static bool is_flat_set = is_flat_set_impl<T>::va
50
51
// We use our own is_integral which does not consider bools integral (to disallow comparison between bool and ints)
51
52
template <typename T> constexpr static bool is_integral = !std::is_same<T, bool >::value &&
52
53
!std::is_same<T, safe<bool >>::value &&
53
- (is_safe<T> || std::is_integral<T>::value);
54
+ (is_safe<T> || std::is_integral<T>::value ||
55
+ std::is_same<T, fc::unsigned_int>::value);
54
56
55
57
// Metafunction to check if two types are comparable, which means not void_t, and either the same or both integral
56
58
template <typename T, typename U>
@@ -74,6 +76,7 @@ const auto& to_num(const I& i) { return i; }
74
76
template <typename I>
75
77
const auto & to_num (const fc::safe<I>& i) { return i.value ; }
76
78
inline auto to_num (const fc::time_point_sec& t) { return t.sec_since_epoch (); }
79
+ inline auto to_num (const fc::unsigned_int& ui) { return ui.value ; }
77
80
78
81
namespace safenum = boost::safe_numerics::safe_compare;
79
82
@@ -397,6 +400,14 @@ struct attribute_assertion<extension<Extension>> {
397
400
};
398
401
}
399
402
};
403
+ template <typename Pointed>
404
+ struct attribute_assertion <std::shared_ptr<Pointed>> {
405
+ static object_restriction_predicate<std::shared_ptr<Pointed>> create (vector<restriction>&& rs) {
406
+ return [p=restrictions_to_predicate<Pointed>(std::move (rs), false )](const shared_ptr<Pointed>& x) {
407
+ return p (*x);
408
+ };
409
+ }
410
+ };
400
411
401
412
template <typename Variant>
402
413
struct variant_assertion {
@@ -465,8 +476,59 @@ object_restriction_predicate<Field> make_predicate(ArgVariant arg) {
465
476
});
466
477
}
467
478
479
+ // A template checking whether a predicate is valid with the provided field type and any restriction argument type
480
+ template <typename Field, typename = void >
481
+ struct predicate_is_valid_for_field {
482
+ template <typename Predicate>
483
+ struct filter {
484
+ template <typename Argument>
485
+ struct argument_filter {
486
+ constexpr static bool value = Predicate::template unwrap<Field, Argument>::valid;
487
+ };
488
+
489
+ constexpr static bool value = typelist::any<restriction::argument_type::list, argument_filter>;
490
+ };
491
+ };
492
+ // Specialization for reflected struct fields; they are always valid because we can use an attribute_assert on them
493
+ template <typename Struct>
494
+ struct predicate_is_valid_for_field <Struct, std::enable_if_t <fc::reflector<Struct>::is_defined::value>> {
495
+ template <typename >
496
+ struct filter { constexpr static bool value = true ; };
497
+ };
498
+ // Specialization for extension fields; they are always valid because we can use an attribute_assert on them
499
+ template <typename Ext>
500
+ struct predicate_is_valid_for_field <extension<Ext>, void > {
501
+ template <typename >
502
+ struct filter { constexpr static bool value = true ; };
503
+ };
504
+ // Specialization for static variant fields; they are always valid because we can use a variant_assert on them
505
+ template <typename ... Ts>
506
+ struct predicate_is_valid_for_field <static_variant<Ts...>, void > {
507
+ template <typename >
508
+ struct filter { constexpr static bool value = true ; };
509
+ };
510
+ // Specialization for shared_ptr fields; they are valid if the thing pointed to is
511
+ template <typename Pointed>
512
+ struct predicate_is_valid_for_field <std::shared_ptr<Pointed>, void >
513
+ : public predicate_is_valid_for_field<std::decay_t <Pointed>> {};
514
+
515
+ // Check if any predicate can be used with the provided field type and any known argument type
516
+ template <typename Field>
517
+ constexpr bool any_predicate_applies () {
518
+ using PredicateTypes = typelist::list<typelist::wrapped<predicate_eq>, typelist::wrapped<predicate_ne>,
519
+ typelist::wrapped<predicate_lt>, typelist::wrapped<predicate_le>,
520
+ typelist::wrapped<predicate_gt>, typelist::wrapped<predicate_ge>,
521
+ typelist::wrapped<predicate_in>, typelist::wrapped<predicate_not_in>,
522
+ typelist::wrapped<predicate_has_all>, typelist::wrapped<predicate_has_none>>;
523
+ return typelist::any<PredicateTypes, predicate_is_valid_for_field<Field>::template filter>;
524
+ }
525
+
468
526
template <typename Field>
469
527
object_restriction_predicate<Field> create_predicate_function (restriction_function func, restriction_argument arg) {
528
+ // This checks that all fields of all objects can be used with at least one predicate
529
+ static_assert (any_predicate_applies<Field>(),
530
+ " This new field type is not yet supported by Custom Active Authorities. Please add support for it." );
531
+
470
532
try {
471
533
switch (func) {
472
534
case restriction::func_eq:
@@ -539,7 +601,7 @@ object_restriction_predicate<Object> create_field_predicate(restriction&& r, sho
539
601
template <typename Object>
540
602
object_restriction_predicate<Object> create_field_predicate (restriction&&, long ) {
541
603
FC_THROW_EXCEPTION (fc::assert_exception, " Invalid restriction references member of non-object type: ${O}" ,
542
- (" O" , fc::get_typename<Object>::name ()));
604
+ (" O" , fc::get_typename<std:: decay_t < Object> >::name ()));
543
605
}
544
606
545
607
template <typename Object>
0 commit comments