Skip to main content

card_game/identifications/
mod.rs

1mod action;
2mod card;
3mod player;
4
5pub use action::*;
6pub use card::*;
7pub use player::*;
8use state_validation::{StateFilterInputCombination, StateFilterInputConversion};
9
10pub trait CastTo<T> {
11    fn cast_ref(&self) -> &T;
12}
13
14/// ID that allows mutation.
15///
16/// Ex. `ValidCardID` -> `MutID<ValidCardID>`
17/// can be used to retrieve a mutable reference to a card
18#[derive(Debug)]
19pub struct MutID<ID>(ID);
20impl<ID> MutID<ID> {
21    pub(crate) fn new(id: ID) -> Self {
22        MutID(id)
23    }
24    pub fn id(&self) -> &ID {
25        &self.0
26    }
27    pub fn take_id(self) -> ID {
28        self.0
29    }
30    pub fn into_id<NewID>(self) -> MutID<NewID>
31    where
32        ID: Into<NewID>,
33    {
34        MutID(self.0.into())
35    }
36}
37pub trait IterMutID<ID> {
38    fn iter_mut_id(self) -> impl Iterator<Item = MutID<ID>>;
39}
40impl<ID> IterMutID<ID> for MutID<Vec<ID>> {
41    fn iter_mut_id(self) -> impl Iterator<Item = MutID<ID>> {
42        self.0.into_iter().map(|id| MutID::new(id))
43    }
44}
45macro_rules! mut_id_for_tuple {
46    ($($index_name: tt => $id: ident),*) => {
47        impl<$($id),*> MutID<($($id),*)> {
48            pub fn split_take(self) -> ($(MutID<$id>),*) {
49                ($(
50                    MutID::new(self.0.$index_name)
51                ),*)
52            }
53        }
54    };
55}
56mut_id_for_tuple!(0 => T0, 1 => T1);
57mut_id_for_tuple!(0 => T0, 1 => T1, 2 => T2);
58mut_id_for_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3);
59impl<T: CastTo<CastedT>, CastedT> CastTo<CastedT> for MutID<T> {
60    fn cast_ref(&self) -> &CastedT {
61        self.0.cast_ref()
62    }
63}
64impl<T: UncheckedReplaceFilter> UncheckedReplaceFilter for MutID<T> {
65    type Output<F> = MutID<T::Output<F>>;
66    fn unchecked_replace_filter<F>(self) -> Self::Output<F> {
67        MutID::new(self.0.unchecked_replace_filter())
68    }
69}
70impl<T: UncheckedClone> UncheckedClone for MutID<T> {
71    fn unchecked_clone(&self) -> Self {
72        MutID::new(self.0.unchecked_clone())
73    }
74}
75#[derive(Debug)]
76pub struct MutIDRemainder<ID>(std::marker::PhantomData<ID>);
77impl<ID> StateFilterInputConversion<ID> for MutID<ID> {
78    type Remainder = MutIDRemainder<ID>;
79    fn split_take(self) -> (ID, Self::Remainder) {
80        (self.0, MutIDRemainder(std::marker::PhantomData::default()))
81    }
82}
83/*impl<T: StateFilterInputConversion<ID>, ID> StateFilterInputConversion<T>
84    for MutID<ID, T::Remainder>
85{
86    type Remainder = MutIDRemainder<ID>;
87    fn split_take(self) -> (ID, Self::Remainder) {
88        (self.0, MutIDRemainder(std::marker::PhantomData::default()))
89    }
90}*/
91impl<NewID, OldID> StateFilterInputCombination<NewID> for MutIDRemainder<OldID> {
92    type Combined = MutID<NewID>;
93    fn combine(self, new_id: NewID) -> Self::Combined {
94        MutID::new(new_id)
95    }
96}
97/*impl<T: StateFilterInputConversion<ID>, ID> StateFilterInputCombination<T> for MutIDRemainder<ID>
98where
99    T::Remainder: StateFilterInputCombination<MutID<ID>>,
100{
101    type Combined = <T::Remainder as StateFilterInputCombination<MutID<ID>>>::Combined;
102    fn combine(self, value: T) -> Self::Combined {
103        let (id, remainder) = value.split_take();
104        remainder.combine(MutID::new(id))
105    }
106}*/
107
108pub trait UncheckedReplaceFilter {
109    type Output<F>;
110    fn unchecked_replace_filter<F>(self) -> Self::Output<F>;
111}
112
113pub trait UncheckedClone {
114    fn unchecked_clone(&self) -> Self;
115}
116
117pub trait FilterSupertype<T> {}
118//impl<T: FilterSupertype<IntoT>, IntoT> FilterSupertype<(T,)> for (IntoT,) {}
119//impl<T> FilterSupertype<()> for T {}
120macro_rules! impl_filter_supertype_for_tuple {
121    ($($list_ty: ident),* | |) => {};
122    ($($list_ty: ident),* | $first_into_ty: ident $(,)? | $($lost_ty: ident),*) => {};
123    ($($list_ty: ident),* | $first_into_ty: ident, $second_into_ty: ident $(,)? | $($lost_ty: ident),*) => {};
124    ($first_ty: ident $(, $list_ty: ident)+ $(,)? | $first_into_ty: ident $(, $list_into_ty: ident)+ | $($lost_ty: ident),*) => {
125        impl<$($list_ty: FilterSupertype<$list_into_ty>,)* $($lost_ty,)* $($list_into_ty,)* $first_ty> FilterSupertype<($($list_into_ty),*)> for ($($list_ty,)* $($lost_ty,)* $first_ty) {}
126        impl_filter_supertype_for_tuple!($($list_ty),* | $($list_into_ty),* | $($lost_ty,)* $first_ty);
127    };
128    ($($list_ty: ident),+ | $($list_into_ty: ident),+ $(,)?) => {
129        impl<$($list_ty: FilterSupertype<$list_into_ty>,)* $($list_into_ty),*> FilterSupertype<($($list_into_ty),*)> for ($($list_ty),*) {}
130        impl_filter_supertype_for_tuple!($($list_ty),* | $($list_into_ty),* |);
131    };
132}
133impl_filter_supertype_for_tuple!(T0, T1 | IntoT0, IntoT1);
134impl_filter_supertype_for_tuple!(T0, T1, T2 | IntoT0, IntoT1, IntoT2);
135impl_filter_supertype_for_tuple!(T0, T1, T2, T3 | IntoT0, IntoT1, IntoT2, IntoT3);
136impl_filter_supertype_for_tuple!(T0, T1, T2, T3, T4 | IntoT0, IntoT1, IntoT2, IntoT3, IntoT4);
137impl_filter_supertype_for_tuple!(
138    T0,
139    T1,
140    T2,
141    T3,
142    T4,
143    T5 | IntoT0,
144    IntoT1,
145    IntoT2,
146    IntoT3,
147    IntoT4,
148    IntoT5,
149);
150impl_filter_supertype_for_tuple!(
151    T0,
152    T1,
153    T2,
154    T3,
155    T4,
156    T5,
157    T6 | IntoT0,
158    IntoT1,
159    IntoT2,
160    IntoT3,
161    IntoT4,
162    IntoT5,
163    IntoT6,
164);
165impl_filter_supertype_for_tuple!(
166    T0,
167    T1,
168    T2,
169    T3,
170    T4,
171    T5,
172    T6,
173    T7 | IntoT0,
174    IntoT1,
175    IntoT2,
176    IntoT3,
177    IntoT4,
178    IntoT5,
179    IntoT6,
180    IntoT7,
181);
182
183/*
184impl<
185    T0: FilterSupertype<IntoT0>,
186    T1: FilterSupertype<IntoT1>,
187    T2: FilterSupertype<IntoT2>,
188    IntoT0,
189    IntoT1,
190    IntoT2,
191> FilterSupertype<(T0, T1, T2)> for (IntoT0, IntoT1, IntoT2)
192{
193}
194impl<
195    T0: FilterSupertype<IntoT0>,
196    T1: FilterSupertype<IntoT1>,
197    T2: FilterSupertype<IntoT2>,
198    T3: FilterSupertype<IntoT3>,
199    IntoT0,
200    IntoT1,
201    IntoT2,
202    IntoT3,
203> FilterSupertype<(T0, T1, T2, T3)> for (IntoT0, IntoT1, IntoT2, IntoT3)
204{
205}*/
206
207#[macro_export]
208macro_rules! create_valid_identification {
209    ($name: ident, $internal_id: ty, with_copy) => {
210        create_valid_identification!($name, $internal_id, core);
211        impl<F> $name<F> {
212            pub fn id(&self) -> $internal_id {
213                self.0
214            }
215        }
216    };
217    ($name: ident, $internal_id: ty, with_clone) => {
218        create_valid_identification!($name, $internal_id, core);
219        impl<F> $name<F> {
220            pub fn id(&self) -> $internal_id {
221                self.0.clone()
222            }
223        }
224    };
225    ($name: ident, $internal_id: ty) => {
226        create_valid_identification!($name, $internal_id, core);
227        impl<F> $name<F> {
228            pub fn id(&self) -> &$internal_id {
229                &self.0
230            }
231        }
232    };
233    ($name: ident, $internal_id: ty, core) => {
234        pub struct $name<F>($internal_id, ::std::marker::PhantomData<(F, *const ())>);
235        impl<F> std::fmt::Debug for $name<F>
236        where
237            $internal_id: std::fmt::Debug,
238        {
239            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240                write!(f, "Valid({:?})", &self.0)
241            }
242        }
243        impl<F> card_game::stack::NonEmptyInput for $name<F> {}
244        impl<F> card_game::identifications::UncheckedReplaceFilter for $name<F> {
245            type Output<NewF> = $name<NewF>;
246            fn unchecked_replace_filter<NewF>(self) -> Self::Output<NewF> {
247                $name(self.0, ::std::marker::PhantomData::default())
248            }
249        }
250        impl<F> card_game::identifications::UncheckedClone for $name<F> {
251            fn unchecked_clone(&self) -> Self {
252                Self(self.0.clone(), ::std::marker::PhantomData::default())
253            }
254        }
255        impl<F> $name<F> {
256            pub fn get<T>(
257                &self,
258                f: impl ::std::ops::FnOnce(&Self) -> ::std::option::Option<&T>,
259            ) -> &T {
260                f(self).unwrap()
261            }
262            pub fn get_mut<T>(
263                &mut self,
264                f: impl ::std::ops::FnOnce(&Self) -> ::std::option::Option<&mut T>,
265            ) -> &mut T {
266                f(self).unwrap()
267            }
268            pub fn remove<T>(
269                &self,
270                f: impl ::std::ops::FnOnce(&Self) -> ::std::option::Option<T>,
271            ) -> T {
272                f(self).unwrap()
273            }
274            pub fn into_filter<NewF>(self) -> $name<NewF>
275            where
276                F: card_game::identifications::FilterSupertype<NewF>,
277            {
278                $name(self.0, ::std::marker::PhantomData::default())
279            }
280        }
281        impl<F> ::std::convert::From<$name<F>> for $internal_id {
282            fn from(valid_id: $name<F>) -> Self {
283                valid_id.0
284            }
285        }
286        impl<F0, F1> ::std::convert::From<$name<(F0, F1)>> for $name<F0> {
287            fn from(valid_id: $name<(F0, F1)>) -> Self {
288                Self(valid_id.0, ::std::marker::PhantomData::default())
289            }
290        }
291        impl<F0, F1, F2> ::std::convert::From<$name<(F0, F1, F2)>> for $name<(F0, F1)> {
292            fn from(valid_id: $name<(F0, F1, F2)>) -> Self {
293                Self(valid_id.0, ::std::marker::PhantomData::default())
294            }
295        }
296        impl<F0, F1, F2, F3> ::std::convert::From<$name<(F0, F1, F2, F3)>> for $name<(F0, F1, F2)> {
297            fn from(valid_id: $name<(F0, F1, F2, F3)>) -> Self {
298                Self(valid_id.0, ::std::marker::PhantomData::default())
299            }
300        }
301        impl<F0, F1, F2, F3, F4> ::std::convert::From<$name<(F0, F1, F2, F3, F4)>>
302            for $name<(F0, F1, F2, F3)>
303        {
304            fn from(valid_id: $name<(F0, F1, F2, F3, F4)>) -> Self {
305                Self(valid_id.0, ::std::marker::PhantomData::default())
306            }
307        }
308        impl<F0, F1, F2, F3, F4, F5> ::std::convert::From<$name<(F0, F1, F2, F3, F4, F5)>>
309            for $name<(F0, F1, F2, F3, F4)>
310        {
311            fn from(valid_id: $name<(F0, F1, F2, F3, F4, F5)>) -> Self {
312                Self(valid_id.0, ::std::marker::PhantomData::default())
313            }
314        }
315        impl<F0, F1, F2, F3, F4, F5, F6> ::std::convert::From<$name<(F0, F1, F2, F3, F4, F5, F6)>>
316            for $name<(F0, F1, F2, F3, F4, F5)>
317        {
318            fn from(valid_id: $name<(F0, F1, F2, F3, F4, F5, F6)>) -> Self {
319                Self(valid_id.0, ::std::marker::PhantomData::default())
320            }
321        }
322        impl<F0, F1, F2, F3, F4, F5, F6, F7>
323            ::std::convert::From<$name<(F0, F1, F2, F3, F4, F5, F6, F7)>>
324            for $name<(F0, F1, F2, F3, F4, F5, F6)>
325        {
326            fn from(valid_id: $name<(F0, F1, F2, F3, F4, F5, F6, F7)>) -> Self {
327                Self(valid_id.0, ::std::marker::PhantomData::default())
328            }
329        }
330        impl<F0, F1> card_game::identifications::CastTo<$name<F0>> for $name<(F0, F1)> {
331            fn cast_ref(&self) -> &$name<F0> {
332                // SAFETY: only type changing the phantom type
333                unsafe { ::std::mem::transmute(self) }
334            }
335        }
336        impl<F0, F1, F2> card_game::identifications::CastTo<$name<(F0, F1)>>
337            for $name<(F0, F1, F2)>
338        {
339            fn cast_ref(&self) -> &$name<(F0, F1)> {
340                // SAFETY: only type changing the phantom type
341                unsafe { ::std::mem::transmute(self) }
342            }
343        }
344        impl<F0, F1, F2, F3> card_game::identifications::CastTo<$name<(F0, F1, F2)>>
345            for $name<(F0, F1, F2, F3)>
346        {
347            fn cast_ref(&self) -> &$name<(F0, F1, F2)> {
348                // SAFETY: only type changing the phantom type
349                unsafe { ::std::mem::transmute(self) }
350            }
351        }
352
353        impl<F> ::std::cmp::PartialEq for $name<F> {
354            fn eq(&self, other: &Self) -> bool {
355                self.0.eq(&other.0)
356            }
357        }
358        impl<F> ::std::cmp::Eq for $name<F> {}
359        impl<F> ::std::hash::Hash for $name<F> {
360            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
361                self.0.hash(state)
362            }
363        }
364    };
365}