referrerpolicy=no-referrer-when-downgrade

fp_coretime/
core_mask.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
19use core::{
20	fmt::Debug,
21	ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
22};
23use scale_info::TypeInfo;
24
25/// The number of bits in the `CoreMask`.
26pub const CORE_MASK_BITS: usize = 80;
27
28// TODO: Use BitArr instead; for this, we'll need to ensure Codec is impl'ed for `BitArr`.
29#[derive(
30	Encode,
31	Decode,
32	DecodeWithMemTracking,
33	Default,
34	Copy,
35	Clone,
36	PartialEq,
37	Eq,
38	Debug,
39	TypeInfo,
40	MaxEncodedLen,
41)]
42pub struct CoreMask([u8; 10]);
43impl CoreMask {
44	pub fn void() -> Self {
45		Self([0u8; 10])
46	}
47	pub fn complete() -> Self {
48		Self([255u8; 10])
49	}
50	pub fn is_void(&self) -> bool {
51		&self.0 == &[0u8; 10]
52	}
53	pub fn is_complete(&self) -> bool {
54		&self.0 == &[255u8; 10]
55	}
56	pub fn set(&mut self, i: u32) -> Self {
57		if i < 80 {
58			self.0[(i / 8) as usize] |= 128 >> (i % 8);
59		}
60		*self
61	}
62	pub fn clear(&mut self, i: u32) -> Self {
63		if i < 80 {
64			self.0[(i / 8) as usize] &= !(128 >> (i % 8));
65		}
66		*self
67	}
68	pub fn count_zeros(&self) -> u32 {
69		self.0.iter().map(|i| i.count_zeros()).sum()
70	}
71	pub fn count_ones(&self) -> u32 {
72		self.0.iter().map(|i| i.count_ones()).sum()
73	}
74	pub fn from_chunk(from: u32, to: u32) -> Self {
75		let mut v = [0u8; 10];
76		for i in (from.min(80) as usize)..(to.min(80) as usize) {
77			v[i / 8] |= 128 >> (i % 8);
78		}
79		Self(v)
80	}
81}
82impl From<u128> for CoreMask {
83	fn from(x: u128) -> Self {
84		let mut v = [0u8; 10];
85		v.iter_mut().rev().fold(x, |a, i| {
86			*i = a as u8;
87			a >> 8
88		});
89		Self(v)
90	}
91}
92impl From<CoreMask> for u128 {
93	fn from(x: CoreMask) -> Self {
94		x.0.into_iter().fold(0u128, |a, i| (a << 8) | i as u128)
95	}
96}
97impl BitAnd<Self> for CoreMask {
98	type Output = Self;
99	fn bitand(mut self, rhs: Self) -> Self {
100		self.bitand_assign(rhs);
101		self
102	}
103}
104impl BitAndAssign<Self> for CoreMask {
105	fn bitand_assign(&mut self, rhs: Self) {
106		for i in 0..10 {
107			self.0[i].bitand_assign(rhs.0[i]);
108		}
109	}
110}
111impl BitOr<Self> for CoreMask {
112	type Output = Self;
113	fn bitor(mut self, rhs: Self) -> Self {
114		self.bitor_assign(rhs);
115		self
116	}
117}
118impl BitOrAssign<Self> for CoreMask {
119	fn bitor_assign(&mut self, rhs: Self) {
120		for i in 0..10 {
121			self.0[i].bitor_assign(rhs.0[i]);
122		}
123	}
124}
125impl BitXor<Self> for CoreMask {
126	type Output = Self;
127	fn bitxor(mut self, rhs: Self) -> Self {
128		self.bitxor_assign(rhs);
129		self
130	}
131}
132impl BitXorAssign<Self> for CoreMask {
133	fn bitxor_assign(&mut self, rhs: Self) {
134		for i in 0..10 {
135			self.0[i].bitxor_assign(rhs.0[i]);
136		}
137	}
138}
139impl Not for CoreMask {
140	type Output = Self;
141	fn not(self) -> Self {
142		let mut result = [0u8; 10];
143		for i in 0..10 {
144			result[i] = self.0[i].not();
145		}
146		Self(result)
147	}
148}
149
150#[cfg(test)]
151mod tests {
152	use super::*;
153
154	#[test]
155	fn complete_works() {
156		assert_eq!(CoreMask::complete(), CoreMask([0xff; 10]));
157		assert!(CoreMask([0xff; 10]).is_complete());
158		for i in 0..80 {
159			assert!(!CoreMask([0xff; 10]).clear(i).is_complete());
160		}
161	}
162
163	#[test]
164	fn void_works() {
165		assert_eq!(CoreMask::void(), CoreMask([0; 10]));
166		assert!(CoreMask([0; 10]).is_void());
167		for i in 0..80 {
168			assert!(!(CoreMask([0; 10]).set(i).is_void()));
169		}
170	}
171
172	#[test]
173	fn from_works() {
174		assert!(CoreMask::from(0xfffff_fffff_fffff_fffff).is_complete());
175		assert_eq!(
176			CoreMask::from(0x12345_67890_abcde_f0123),
177			CoreMask([0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x01, 0x23]),
178		);
179	}
180
181	#[test]
182	fn into_works() {
183		assert_eq!(u128::from(CoreMask::complete()), 0xfffff_fffff_fffff_fffff);
184		assert_eq!(
185			0x12345_67890_abcde_f0123u128,
186			CoreMask([0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x01, 0x23]).into(),
187		);
188	}
189
190	#[test]
191	fn chunk_works() {
192		assert_eq!(CoreMask::from_chunk(40, 60), CoreMask::from(0x00000_00000_fffff_00000),);
193	}
194
195	#[test]
196	fn bit_or_works() {
197		assert_eq!(
198			CoreMask::from(0x02040_a0c0e_d0a0b_0ffff) | CoreMask::from(0x10305_0b0d0_0e0d0_e0000),
199			CoreMask::from(0x12345_abcde_deadb_effff),
200		);
201	}
202
203	#[test]
204	fn bit_or_assign_works() {
205		let mut a = CoreMask::from(0x02040_a0c0e_d0a0b_0ffff);
206		a |= CoreMask::from(0x10305_0b0d0_0e0d0_e0000);
207		assert_eq!(a, CoreMask::from(0x12345_abcde_deadb_effff));
208	}
209
210	#[test]
211	fn bit_and_works() {
212		assert_eq!(
213			CoreMask::from(0x00000_abcde_deadb_efff0) & CoreMask::from(0x02040_00000_d0a0b_0ff0f),
214			CoreMask::from(0x00000_00000_d0a0b_0ff00),
215		);
216	}
217
218	#[test]
219	fn bit_and_assign_works() {
220		let mut a = CoreMask::from(0x00000_abcde_deadb_efff0);
221		a &= CoreMask::from(0x02040_00000_d0a0b_0ff0f);
222		assert_eq!(a, CoreMask::from(0x00000_00000_d0a0b_0ff00));
223	}
224
225	#[test]
226	fn bit_xor_works() {
227		assert_eq!(
228			CoreMask::from(0x10010_10010_10010_10010) ^ CoreMask::from(0x01110_01110_01110_01110),
229			CoreMask::from(0x11100_11100_11100_11100),
230		);
231	}
232
233	#[test]
234	fn bit_xor_assign_works() {
235		let mut a = CoreMask::from(0x10010_10010_10010_10010);
236		a ^= CoreMask::from(0x01110_01110_01110_01110);
237		assert_eq!(a, CoreMask::from(0x11100_11100_11100_11100));
238	}
239}