primitive_types/
lib.rs

1// Copyright 2020 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Primitive types shared by Substrate and Parity Ethereum.
10//!
11//! Those are uint types `U128`, `U256` and `U512`, and fixed hash types `H160`,
12//! `H256` and `H512`, with optional serde serialization, parity-scale-codec and
13//! rlp encoding.
14
15#![cfg_attr(not(feature = "std"), no_std)]
16
17#[cfg(feature = "fp-conversion")]
18mod fp_conversion;
19
20use core::convert::TryFrom;
21use fixed_hash::{construct_fixed_hash, impl_fixed_hash_conversions};
22#[cfg(feature = "scale-info")]
23use scale_info_crate::TypeInfo;
24use uint::{construct_uint, uint_full_mul_reg};
25
26/// Error type for conversion.
27#[derive(Debug, PartialEq, Eq)]
28pub enum Error {
29	/// Overflow encountered.
30	Overflow,
31}
32
33construct_uint! {
34	/// 128-bit unsigned integer.
35	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
36	pub struct U128(2);
37}
38construct_uint! {
39	/// 256-bit unsigned integer.
40	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
41	pub struct U256(4);
42}
43construct_uint! {
44	/// 512-bits unsigned integer.
45	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
46	pub struct U512(8);
47}
48
49construct_fixed_hash! {
50	/// Fixed-size uninterpreted hash type with 16 bytes (128 bits) size.
51	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
52	pub struct H128(16);
53}
54
55construct_fixed_hash! {
56	/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
57	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
58	pub struct H160(20);
59}
60construct_fixed_hash! {
61	/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
62	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
63	pub struct H256(32);
64}
65construct_fixed_hash! {
66	/// Fixed-size uninterpreted hash type with 48 bytes (384 bits) size.
67	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
68	pub struct H384(48);
69}
70construct_fixed_hash! {
71	/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
72	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
73	pub struct H512(64);
74}
75construct_fixed_hash! {
76	/// Fixed-size uninterpreted hash type with 96 bytes (768 bits) size.
77	#[cfg_attr(feature = "scale-info", derive(TypeInfo))]
78	pub struct H768(96);
79}
80
81#[cfg(feature = "num-traits")]
82mod num_traits {
83	use super::*;
84	use impl_num_traits::impl_uint_num_traits;
85
86	impl_uint_num_traits!(U128, 2);
87	impl_uint_num_traits!(U256, 4);
88	impl_uint_num_traits!(U512, 8);
89}
90
91#[cfg(feature = "impl-serde")]
92mod serde {
93	use super::*;
94	use impl_serde::{impl_fixed_hash_serde, impl_uint_serde};
95
96	impl_uint_serde!(U128, 2);
97	impl_uint_serde!(U256, 4);
98	impl_uint_serde!(U512, 8);
99
100	impl_fixed_hash_serde!(H128, 16);
101	impl_fixed_hash_serde!(H160, 20);
102	impl_fixed_hash_serde!(H256, 32);
103	impl_fixed_hash_serde!(H384, 48);
104	impl_fixed_hash_serde!(H512, 64);
105	impl_fixed_hash_serde!(H768, 96);
106}
107
108// true that no need std, but need to do no_std alloc than, so simplified for now
109// also no macro, but easy to create
110#[cfg(all(feature = "std", feature = "json-schema"))]
111mod json_schema {
112	use super::*;
113
114	impl schemars::JsonSchema for H160 {
115		fn schema_name() -> String {
116			"0xPrefixedHexString".to_string()
117		}
118
119		fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
120			String::json_schema(gen)
121		}
122	}
123}
124
125#[cfg(feature = "impl-codec")]
126mod codec {
127	use super::*;
128	use impl_codec::{impl_fixed_hash_codec, impl_uint_codec};
129
130	impl_uint_codec!(U128, 2);
131	impl_uint_codec!(U256, 4);
132	impl_uint_codec!(U512, 8);
133
134	impl_fixed_hash_codec!(H128, 16);
135	impl_fixed_hash_codec!(H160, 20);
136	impl_fixed_hash_codec!(H256, 32);
137	impl_fixed_hash_codec!(H384, 48);
138	impl_fixed_hash_codec!(H512, 64);
139	impl_fixed_hash_codec!(H768, 96);
140}
141
142#[cfg(feature = "impl-rlp")]
143mod rlp {
144	use super::*;
145	use impl_rlp::{impl_fixed_hash_rlp, impl_uint_rlp};
146
147	impl_uint_rlp!(U128, 2);
148	impl_uint_rlp!(U256, 4);
149	impl_uint_rlp!(U512, 8);
150
151	impl_fixed_hash_rlp!(H128, 16);
152	impl_fixed_hash_rlp!(H160, 20);
153	impl_fixed_hash_rlp!(H256, 32);
154	impl_fixed_hash_rlp!(H384, 48);
155	impl_fixed_hash_rlp!(H512, 64);
156	impl_fixed_hash_rlp!(H768, 96);
157}
158
159impl_fixed_hash_conversions!(H256, H160);
160
161impl U128 {
162	/// Multiplies two 128-bit integers to produce full 256-bit integer.
163	/// Overflow is not possible.
164	#[inline(always)]
165	pub fn full_mul(self, other: U128) -> U256 {
166		U256(uint_full_mul_reg!(U128, 2, self, other))
167	}
168}
169
170impl U256 {
171	/// Multiplies two 256-bit integers to produce full 512-bit integer.
172	/// Overflow is not possible.
173	#[inline(always)]
174	pub fn full_mul(self, other: U256) -> U512 {
175		U512(uint_full_mul_reg!(U256, 4, self, other))
176	}
177}
178
179impl From<U256> for U512 {
180	fn from(value: U256) -> U512 {
181		let U256(ref arr) = value;
182		let mut ret = [0; 8];
183		ret[0] = arr[0];
184		ret[1] = arr[1];
185		ret[2] = arr[2];
186		ret[3] = arr[3];
187		U512(ret)
188	}
189}
190
191impl TryFrom<U256> for U128 {
192	type Error = Error;
193
194	fn try_from(value: U256) -> Result<U128, Error> {
195		let U256(ref arr) = value;
196		if arr[2] | arr[3] != 0 {
197			return Err(Error::Overflow)
198		}
199		let mut ret = [0; 2];
200		ret[0] = arr[0];
201		ret[1] = arr[1];
202		Ok(U128(ret))
203	}
204}
205
206impl TryFrom<U512> for U256 {
207	type Error = Error;
208
209	fn try_from(value: U512) -> Result<U256, Error> {
210		let U512(ref arr) = value;
211		if arr[4] | arr[5] | arr[6] | arr[7] != 0 {
212			return Err(Error::Overflow)
213		}
214		let mut ret = [0; 4];
215		ret[0] = arr[0];
216		ret[1] = arr[1];
217		ret[2] = arr[2];
218		ret[3] = arr[3];
219		Ok(U256(ret))
220	}
221}
222
223impl TryFrom<U512> for U128 {
224	type Error = Error;
225
226	fn try_from(value: U512) -> Result<U128, Error> {
227		let U512(ref arr) = value;
228		if arr[2] | arr[3] | arr[4] | arr[5] | arr[6] | arr[7] != 0 {
229			return Err(Error::Overflow)
230		}
231		let mut ret = [0; 2];
232		ret[0] = arr[0];
233		ret[1] = arr[1];
234		Ok(U128(ret))
235	}
236}
237
238impl From<U128> for U512 {
239	fn from(value: U128) -> U512 {
240		let U128(ref arr) = value;
241		let mut ret = [0; 8];
242		ret[0] = arr[0];
243		ret[1] = arr[1];
244		U512(ret)
245	}
246}
247
248impl From<U128> for U256 {
249	fn from(value: U128) -> U256 {
250		let U128(ref arr) = value;
251		let mut ret = [0; 4];
252		ret[0] = arr[0];
253		ret[1] = arr[1];
254		U256(ret)
255	}
256}
257
258impl<'a> From<&'a U256> for U512 {
259	fn from(value: &'a U256) -> U512 {
260		let U256(ref arr) = *value;
261		let mut ret = [0; 8];
262		ret[0] = arr[0];
263		ret[1] = arr[1];
264		ret[2] = arr[2];
265		ret[3] = arr[3];
266		U512(ret)
267	}
268}
269
270impl<'a> TryFrom<&'a U512> for U256 {
271	type Error = Error;
272
273	fn try_from(value: &'a U512) -> Result<U256, Error> {
274		let U512(ref arr) = *value;
275		if arr[4] | arr[5] | arr[6] | arr[7] != 0 {
276			return Err(Error::Overflow)
277		}
278		let mut ret = [0; 4];
279		ret[0] = arr[0];
280		ret[1] = arr[1];
281		ret[2] = arr[2];
282		ret[3] = arr[3];
283		Ok(U256(ret))
284	}
285}