git.delta.rocks / unique-network / refs/commits / 5ec9dbee0705

difftreelog

refactor LazyValue without generic Fn

Daniel Shiposha2023-10-11parent: #5a68a95.patch.diff
in: master

1 file changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
53#![cfg_attr(not(feature = "std"), no_std)]53#![cfg_attr(not(feature = "std"), no_std)]
54extern crate alloc;54extern crate alloc;
5555
56use alloc::boxed::Box;
56use core::{57use core::{
57 marker::PhantomData,58 marker::PhantomData,
58 ops::{Deref, DerefMut},59 ops::{Deref, DerefMut},
59 slice::from_ref,60 slice::from_ref,
61 unreachable,
60};62};
6163
62use evm_coder::ToLog;64use evm_coder::ToLog;
871 >;873 >;
872}874}
875
876enum LazyValueState<'a, T> {
877 Pending(Box<dyn FnOnce() -> T + 'a>),
878 InProgress(PhantomData<sp_std::cell::Cell<T>>),
879 Computed(T),
880}
873881
874/// Value representation with delayed initialization time.882/// Value representation with delayed initialization time.
875pub struct LazyValue<T, F> {883pub struct LazyValue<'a, T> {
876 value: Option<T>,884 state: LazyValueState<'a, T>,
877 f: Option<F>,
878}885}
879886
880impl<T, F: FnOnce() -> T> LazyValue<T, F> {887impl<'a, T> LazyValue<'a, T> {
881 /// Create a new LazyValue.888 /// Create a new LazyValue.
882 pub fn new(f: F) -> Self {889 pub fn new(f: impl FnOnce() -> T + 'a) -> Self {
883 Self {890 Self {
884 value: None,
885 f: Some(f),891 state: LazyValueState::Pending(Box::new(f)),
886 }892 }
887 }893 }
888894
889 /// Get the value. If it is called the first time, the value will be initialized.895 /// Get the value. If it is called the first time, the value will be initialized.
890 pub fn value(&mut self) -> &T {896 pub fn value(&mut self) -> &T {
891 self.force_value();897 self.force_value();
892 self.value.as_ref().unwrap()898 self.value_mut()
893 }899 }
894900
895 /// Get the value. If it is called the first time, the value will be initialized.901 /// Get the value. If it is called the first time, the value will be initialized.
896 pub fn value_mut(&mut self) -> &mut T {902 pub fn value_mut(&mut self) -> &mut T {
897 self.force_value();903 self.force_value();
904
898 self.value.as_mut().unwrap()905 if let LazyValueState::Computed(value) = &mut self.state {
906 value
907 } else {
908 unreachable!()
909 }
899 }910 }
900911
901 fn into_inner(mut self) -> T {912 fn into_inner(mut self) -> T {
902 self.force_value();913 self.force_value();
903 self.value.unwrap()914 if let LazyValueState::Computed(value) = self.state {
915 value
916 } else {
917 unreachable!()
918 }
904 }919 }
905920
906 /// Is value initialized?921 /// Is value initialized?
907 pub fn has_value(&self) -> bool {922 pub fn has_value(&self) -> bool {
908 self.value.is_some()923 matches!(self.state, LazyValueState::Computed(_))
909 }924 }
910925
911 fn force_value(&mut self) {926 fn force_value(&mut self) {
927 use LazyValueState::*;
928
912 if self.value.is_none() {929 if self.has_value() {
930 return;
931 }
932
933 match sp_std::mem::replace(&mut self.state, InProgress(PhantomData)) {
913 self.value = Some(self.f.take().unwrap()())934 Pending(f) => self.state = Computed(f()),
935 _ => {
936 // Computed is ruled out by the above condition
937 // InProgress is ruled out by not implementing Sync and absence of recursion
938 unreachable!()
939 }
914 }940 }
915 }941 }
916}942}
917943
918fn check_token_permissions<T, FCA, FTO, FTE>(944fn check_token_permissions<T: Config>(
919 collection_admin_permitted: bool,945 collection_admin_permitted: bool,
920 token_owner_permitted: bool,946 token_owner_permitted: bool,
921 is_collection_admin: &mut LazyValue<bool, FCA>,947 is_collection_admin: &mut LazyValue<bool>,
922 is_token_owner: &mut LazyValue<Result<bool, DispatchError>, FTO>,948 is_token_owner: &mut LazyValue<Result<bool, DispatchError>>,
923 is_token_exist: &mut LazyValue<bool, FTE>,949 is_token_exist: &mut LazyValue<bool>,
924) -> DispatchResult950) -> DispatchResult {
925where
926 T: Config,
927 FCA: FnOnce() -> bool,
928 FTO: FnOnce() -> Result<bool, DispatchError>,
929 FTE: FnOnce() -> bool,
930{
931 if !(collection_admin_permitted && *is_collection_admin.value()951 if !(collection_admin_permitted && *is_collection_admin.value()
932 || token_owner_permitted && (*is_token_owner.value())?)952 || token_owner_permitted && (*is_token_owner.value())?)
2346/// This type utilizes the lazy evaluation to avoid repeating the computation2366/// This type utilizes the lazy evaluation to avoid repeating the computation
2347/// of several performance-heavy or PoV-heavy tasks,2367/// of several performance-heavy or PoV-heavy tasks,
2348/// such as checking the indirect ownership or reading the token property permissions.2368/// such as checking the indirect ownership or reading the token property permissions.
2349pub struct PropertyWriter<'a, WriterVariant, T, Handle, FIsAdmin, FPropertyPermissions> {2369pub struct PropertyWriter<'a, WriterVariant, T, Handle> {
2350 collection: &'a Handle,2370 collection: &'a Handle,
2351 collection_lazy_info: PropertyWriterLazyCollectionInfo<FIsAdmin, FPropertyPermissions>,2371 collection_lazy_info: PropertyWriterLazyCollectionInfo<'a>,
2352 _phantom: PhantomData<(T, WriterVariant)>,2372 _phantom: PhantomData<(T, WriterVariant)>,
2353}2373}
23542374
2355impl<'a, T, Handle, WriterVariant, FIsAdmin, FPropertyPermissions>2375impl<'a, T, Handle, WriterVariant> PropertyWriter<'a, WriterVariant, T, Handle>
2356 PropertyWriter<'a, WriterVariant, T, Handle, FIsAdmin, FPropertyPermissions>
2357where2376where
2358 T: Config,2377 T: Config,
2359 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2378 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2360 FIsAdmin: FnOnce() -> bool,
2361 FPropertyPermissions: FnOnce() -> PropertiesPermissionMap,
2362{2379{
2363 fn internal_write_token_properties<FCheckTokenExist, FCheckTokenOwner, FGetProperties>(2380 fn internal_write_token_properties(
2364 &mut self,2381 &mut self,
2365 token_id: TokenId,2382 token_id: TokenId,
2366 mut token_lazy_info: PropertyWriterLazyTokenInfo<2383 mut token_lazy_info: PropertyWriterLazyTokenInfo,
2367 FCheckTokenExist,
2368 FCheckTokenOwner,
2369 FGetProperties,
2370 >,
2371 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,2384 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
2372 log: evm_coder::ethereum::Log,2385 log: evm_coder::ethereum::Log,
2373 ) -> DispatchResult2386 ) -> DispatchResult {
2374 where
2375 FCheckTokenExist: FnOnce() -> bool,
2376 FCheckTokenOwner: FnOnce() -> Result<bool, DispatchError>,
2377 FGetProperties: FnOnce() -> TokenProperties,
2378 {
2379 for (key, value) in properties_updates {2387 for (key, value) in properties_updates {
2380 let permission = self2388 let permission = self
2400 collection_admin,2408 collection_admin,
2401 token_owner,2409 token_owner,
2402 ..2410 ..
2403 } => check_token_permissions::<T, _, _, _>(2411 } => check_token_permissions::<T>(
2404 collection_admin,2412 collection_admin,
2405 token_owner,2413 token_owner,
2406 &mut self.collection_lazy_info.is_collection_admin,2414 &mut self.collection_lazy_info.is_collection_admin,
2454/// A helper structure for the [`PropertyWriter`] that holds2462/// A helper structure for the [`PropertyWriter`] that holds
2455/// the collection-related info. The info is loaded using lazy evaluation.2463/// the collection-related info. The info is loaded using lazy evaluation.
2456/// This info is common for any token for which we write properties.2464/// This info is common for any token for which we write properties.
2457pub struct PropertyWriterLazyCollectionInfo<FIsAdmin, FPropertyPermissions> {2465pub struct PropertyWriterLazyCollectionInfo<'a> {
2458 is_collection_admin: LazyValue<bool, FIsAdmin>,2466 is_collection_admin: LazyValue<'a, bool>,
2459 property_permissions: LazyValue<PropertiesPermissionMap, FPropertyPermissions>,2467 property_permissions: LazyValue<'a, PropertiesPermissionMap>,
2460}2468}
24612469
2462/// A helper structure for the [`PropertyWriter`] that holds2470/// A helper structure for the [`PropertyWriter`] that holds
2463/// the token-related info. The info is loaded using lazy evaluation.2471/// the token-related info. The info is loaded using lazy evaluation.
2464pub struct PropertyWriterLazyTokenInfo<FCheckTokenExist, FCheckTokenOwner, FGetProperties> {2472pub struct PropertyWriterLazyTokenInfo<'a> {
2465 is_token_exist: LazyValue<bool, FCheckTokenExist>,2473 is_token_exist: LazyValue<'a, bool>,
2466 is_token_owner: LazyValue<Result<bool, DispatchError>, FCheckTokenOwner>,2474 is_token_owner: LazyValue<'a, Result<bool, DispatchError>>,
2467 stored_properties: LazyValue<TokenProperties, FGetProperties>,2475 stored_properties: LazyValue<'a, TokenProperties>,
2468}2476}
24692477
2470impl<FCheckTokenExist, FCheckTokenOwner, FGetProperties>2478impl<'a> PropertyWriterLazyTokenInfo<'a> {
2471 PropertyWriterLazyTokenInfo<FCheckTokenExist, FCheckTokenOwner, FGetProperties>
2472where
2473 FCheckTokenExist: FnOnce() -> bool,
2474 FCheckTokenOwner: FnOnce() -> Result<bool, DispatchError>,
2475 FGetProperties: FnOnce() -> TokenProperties,
2476{
2477 /// Create a lazy token info.2479 /// Create a lazy token info.
2478 pub fn new(2480 pub fn new(
2479 check_token_exist: FCheckTokenExist,2481 check_token_exist: impl FnOnce() -> bool + 'a,
2480 check_token_owner: FCheckTokenOwner,2482 check_token_owner: impl FnOnce() -> Result<bool, DispatchError> + 'a,
2481 get_token_properties: FGetProperties,2483 get_token_properties: impl FnOnce() -> TokenProperties + 'a,
2482 ) -> Self {2484 ) -> Self {
2483 Self {2485 Self {
2484 is_token_exist: LazyValue::new(check_token_exist),2486 is_token_exist: LazyValue::new(check_token_exist),
2500 'a,
2501 Self,
2502 T,
2503 Handle,
2504 impl FnOnce() -> bool + 'a,
2505 impl FnOnce() -> PropertiesPermissionMap + 'a,
2506 >
2507 where2502 where
2508 T: Config,2503 T: Config,
2521 }2516 }
2522}2517}
25232518
2524impl<'a, T, Handle, FIsAdmin, FPropertyPermissions>2519impl<'a, T, Handle> PropertyWriter<'a, NewTokenPropertyWriter<T>, T, Handle>
2525 PropertyWriter<'a, NewTokenPropertyWriter<T>, T, Handle, FIsAdmin, FPropertyPermissions>
2526where2520where
2527 T: Config,2521 T: Config,
2528 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2522 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2529 FIsAdmin: FnOnce() -> bool,
2530 FPropertyPermissions: FnOnce() -> PropertiesPermissionMap,
2531{2523{
2532 /// A function to write properties to a **newly created** token.2524 /// A function to write properties to a **newly created** token.
2533 pub fn write_token_properties(2525 pub fn write_token_properties(
2574 'a,
2575 Self,
2576 T,
2577 Handle,
2578 impl FnOnce() -> bool + 'a,
2579 impl FnOnce() -> PropertiesPermissionMap + 'a,
2580 >
2581 where2566 where
2582 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2567 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2594 }2579 }
2595}2580}
25962581
2597impl<'a, T, Handle, FIsAdmin, FPropertyPermissions>2582impl<'a, T, Handle> PropertyWriter<'a, ExistingTokenPropertyWriter<T>, T, Handle>
2598 PropertyWriter<'a, ExistingTokenPropertyWriter<T>, T, Handle, FIsAdmin, FPropertyPermissions>
2599where2583where
2600 T: Config,2584 T: Config,
2601 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2585 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2602 FIsAdmin: FnOnce() -> bool,
2603 FPropertyPermissions: FnOnce() -> PropertiesPermissionMap,
2604{2586{
2605 /// A function to write properties to an **already existing** token.2587 /// A function to write properties to an **already existing** token.
2606 pub fn write_token_properties(2588 pub fn write_token_properties(
2643#[cfg(feature = "runtime-benchmarks")]2625#[cfg(feature = "runtime-benchmarks")]
2644impl<T: Config> BenchmarkPropertyWriter<T> {2626impl<T: Config> BenchmarkPropertyWriter<T> {
2645 /// Creates a [`PropertyWriter`] for benchmarking tokens properties writing.2627 /// Creates a [`PropertyWriter`] for benchmarking tokens properties writing.
2646 pub fn new<'a, Handle, FIsAdmin, FPropertyPermissions>(2628 pub fn new<'a, Handle>(
2647 collection: &Handle,2629 collection: &Handle,
2648 collection_lazy_info: PropertyWriterLazyCollectionInfo<FIsAdmin, FPropertyPermissions>,2630 collection_lazy_info: PropertyWriterLazyCollectionInfo,
2649 ) -> PropertyWriter<Self, T, Handle, FIsAdmin, FPropertyPermissions>2631 ) -> PropertyWriter<'a, Self, T, Handle>
2650 where2632 where
2651 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2633 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2652 FIsAdmin: FnOnce() -> bool,
2653 FPropertyPermissions: FnOnce() -> PropertiesPermissionMap,
2654 {2634 {
2655 PropertyWriter {2635 PropertyWriter {
2656 collection,2636 collection,
2663 pub fn load_collection_info<Handle>(2643 pub fn load_collection_info<Handle>(
2664 collection_handle: &Handle,2644 collection_handle: &Handle,
2665 sender: &T::CrossAccountId,2645 sender: &T::CrossAccountId,
2666 ) -> PropertyWriterLazyCollectionInfo<2646 ) -> PropertyWriterLazyCollectionInfo<'static>
2667 impl FnOnce() -> bool,
2668 impl FnOnce() -> PropertiesPermissionMap,
2669 >
2670 where2647 where
2671 Handle: Deref<Target = CollectionHandle<T>>,2648 Handle: Deref<Target = CollectionHandle<T>>,
2683 pub fn load_token_properties<Handle>(2660 pub fn load_token_properties<Handle>(
2684 collection: &Handle,2661 collection: &Handle,
2685 token_id: TokenId,2662 token_id: TokenId,
2686 ) -> PropertyWriterLazyTokenInfo<2663 ) -> PropertyWriterLazyTokenInfo
2687 impl FnOnce() -> bool,
2688 impl FnOnce() -> Result<bool, DispatchError>,
2689 impl FnOnce() -> TokenProperties,
2690 >
2691 where2664 where
2692 Handle: CommonCollectionOperations<T>,2665 Handle: CommonCollectionOperations<T>,
2693 {2666 {
2704}2677}
27052678
2706#[cfg(feature = "runtime-benchmarks")]2679#[cfg(feature = "runtime-benchmarks")]
2707impl<'a, T, Handle, FIsAdmin, FPropertyPermissions>2680impl<'a, T, Handle> PropertyWriter<'a, BenchmarkPropertyWriter<T>, T, Handle>
2708 PropertyWriter<'a, BenchmarkPropertyWriter<T>, T, Handle, FIsAdmin, FPropertyPermissions>
2709where2681where
2710 T: Config,2682 T: Config,
2711 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,2683 Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
2712 FIsAdmin: FnOnce() -> bool,
2713 FPropertyPermissions: FnOnce() -> PropertiesPermissionMap,
2714{2684{
2715 /// A function to benchmark the writing of token properties.2685 /// A function to benchmark the writing of token properties.
2716 pub fn write_token_properties(2686 pub fn write_token_properties(
2826 /* 15*/ TestCase::new(1, 1, 1, 1, 0),2796 /* 15*/ TestCase::new(1, 1, 1, 1, 0),
2827 ];2797 ];
28282798
2829 pub fn check_token_permissions<T, FCA, FTO, FTE>(2799 pub fn check_token_permissions<T: Config>(
2830 collection_admin_permitted: bool,2800 collection_admin_permitted: bool,
2831 token_owner_permitted: bool,2801 token_owner_permitted: bool,
2832 is_collection_admin: &mut LazyValue<bool, FCA>,2802 is_collection_admin: &mut LazyValue<bool>,
2833 check_token_ownership: &mut LazyValue<Result<bool, DispatchError>, FTO>,2803 check_token_ownership: &mut LazyValue<Result<bool, DispatchError>>,
2834 check_token_existence: &mut LazyValue<bool, FTE>,2804 check_token_existence: &mut LazyValue<bool>,
2835 ) -> DispatchResult2805 ) -> DispatchResult {
2836 where
2837 T: Config,
2838 FCA: FnOnce() -> bool,
2839 FTO: FnOnce() -> Result<bool, DispatchError>,
2840 FTE: FnOnce() -> bool,
2841 {
2842 crate::check_token_permissions::<T, FCA, FTO, FTE>(2806 crate::check_token_permissions::<T>(
2843 collection_admin_permitted,2807 collection_admin_permitted,
2844 token_owner_permitted,2808 token_owner_permitted,
2845 is_collection_admin,2809 is_collection_admin,