1#![no_std]
2
3macro_rules! if_feature {
13 ($s:literal, $($i:item)*) => ($(
14 #[cfg(feature = $s)] $i
15 )*)
16}
17
18if_feature!("std", extern crate std; use std::hash::{Hash, Hasher};);
19
20if_feature!(
21 "serde",
22 use std::{convert::TryInto, marker::PhantomData, fmt, vec::Vec};
23 use serde::{
24 de::{Deserialize, Deserializer, Error, SeqAccess, Visitor},
25 ser::{Serialize, Serializer, SerializeSeq},
26 };
27);
28
29pub type UnorderedPair<T> = UnorderedNTuple<T, 2>;
35
36impl<T> From<(T, T)> for UnorderedPair<T> {
37 fn from(tuple: (T, T)) -> Self {
38 Self([tuple.0, tuple.1])
39 }
40}
41impl<T> From<UnorderedPair<T>> for (T, T) {
42 fn from(pair: UnorderedPair<T>) -> (T, T) {
43 let [first, second] = pair.0;
44 (first, second)
45 }
46}
47
48#[derive(Copy, Clone, Debug, Eq)]
58pub struct UnorderedNTuple<T, const N: usize>(pub [T; N]);
59
60impl<T, const N: usize> From<[T; N]> for UnorderedNTuple<T, N> {
61 fn from(arg: [T; N]) -> Self {
62 Self(arg)
63 }
64}
65
66impl<T, const N: usize> From<UnorderedNTuple<T, N>> for [T; N] {
67 fn from(arg: UnorderedNTuple<T, N>) -> Self {
68 arg.0
69 }
70}
71
72impl<T, const N: usize> PartialEq for UnorderedNTuple<T, N>
73where
74 T: PartialEq,
75{
76 fn eq(&self, other: &UnorderedNTuple<T, N>) -> bool {
77 let mut used_indices = [false; N];
78 for element in self.0.iter() {
79 let mut found = false;
80 for (index, other_element) in other.0.iter().enumerate() {
81 if used_indices[index] {
82 continue;
83 }
84 if element == other_element {
85 used_indices[index] = true;
86 found = true;
87 break;
88 }
89 }
90 if !found {
91 return false;
92 }
93 }
94 true
95 }
96}
97
98if_feature!(
99 "std",
100 impl<T, const N: usize> Hash for UnorderedNTuple<T, N>
101 where
102 T: Hash + Ord + Clone,
103 {
104 fn hash<H: Hasher>(&self, state: &mut H) {
105 let mut sorted = self.0.clone();
106 sorted.sort();
107 Hash::hash_slice(&sorted, state);
108 }
109 }
110);
111
112if_feature!(
113 "serde",
114 impl<T: Serialize, const N: usize> Serialize for UnorderedNTuple<T, N> {
115 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116 where
117 S: Serializer,
118 {
119 let mut seq = serializer.serialize_seq(Some(N))?;
120 for item in self.0.iter() {
121 seq.serialize_element(item)?;
122 }
123 seq.end()
124 }
125 }
126 struct UnorderedNTupleVisitor<T, const N: usize> {
127 _phantom: PhantomData<fn() -> [T; N]>,
128 }
129 impl<T, const N: usize> UnorderedNTupleVisitor<T, N> {
130 fn new() -> Self {
131 Self {
132 _phantom: PhantomData,
133 }
134 }
135 }
136 impl<'de, T, const N: usize> Visitor<'de> for UnorderedNTupleVisitor<T, N>
137 where
138 T: Deserialize<'de>,
139 {
140 type Value = UnorderedNTuple<T, N>;
141
142 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
143 f.write_str("Expecting a sequence with N homogenous elements of type T")
144 }
145
146 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
147 where
148 S: SeqAccess<'de>,
149 {
150 if access.size_hint() != Some(N) {
151 return Err(S::Error::custom("Wrong number of elements"));
152 }
153 let mut data: Vec<T> = Vec::new();
154 for _ in 0..N {
155 data.push(access.next_element()?.unwrap())
156 }
157 Ok(UnorderedNTuple(
158 data.try_into().unwrap_or_else(|_| unreachable!()),
159 ))
160 }
161 }
162 impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for UnorderedNTuple<T, N> {
163 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
164 where
165 D: Deserializer<'de>,
166 {
167 deserializer.deserialize_seq(UnorderedNTupleVisitor::<T, N>::new())
168 }
169 }
170);