Skip to main content

callable/
argument.rs

1use core::marker::PhantomData;
2
3pub use first::FirstArgumentProvided;
4pub use last::LastArgumentProvided;
5pub use ByMut as r#mut;
6pub use ByRef as r#ref;
7pub use Value as value;
8
9pub trait Argument<'a, ImplicitBounds = &'a Self> {
10    type Argument;
11}
12
13pub trait ArgumentType: for<'a> Argument<'a> {
14    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self>;
15}
16
17pub trait ProvideArgument {
18    type ProvideArgumentType: ArgumentType;
19
20    // fn provide_argument(&self) -> <Self::ProvideArgumentType as ArgumentType<'_>>::Argument;
21
22    fn provide_argument_to<
23        Out,
24        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
25    >(
26        &self,
27        f: F,
28    ) -> Out;
29}
30
31/// Don't try to remember the name, use [`ArgumentType`](crate::ArgumentType) instead.
32pub struct Value<T>(PhantomData<T>, Invalid);
33/// Don't try to remember the name, use [`ArgumentType`](crate::ArgumentType) instead.
34pub struct ByRef<T: ?Sized>(PhantomData<T>, Invalid);
35/// Don't try to remember the name, use [`ArgumentType`](crate::ArgumentType) instead.
36pub struct ByMut<T: ?Sized>(PhantomData<T>, Invalid);
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct Copied<T: Copy>(pub(super) T);
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub struct Cloned<T: Clone>(pub(super) T);
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub struct Refed<T>(pub(super) T);
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub struct With<Cbk>(pub(super) Cbk);
47
48impl<'a, T> Argument<'a> for Value<T> {
49    type Argument = T;
50}
51
52impl<T> ArgumentType for Value<T> {
53    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self> {
54        arg
55    }
56}
57
58impl<'a, T: ?Sized> Argument<'a> for ByRef<T> {
59    type Argument = &'a T;
60}
61
62impl<T: ?Sized> ArgumentType for ByRef<T> {
63    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self> {
64        arg
65    }
66}
67
68impl<'a, T: ?Sized> Argument<'a> for ByMut<T> {
69    type Argument = &'a mut T;
70}
71
72impl<T: ?Sized> ArgumentType for ByMut<T> {
73    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self> {
74        arg
75    }
76}
77
78impl<T: Copy> ProvideArgument for Copied<T> {
79    type ProvideArgumentType = Value<T>;
80
81    // fn provide_argument(&self) -> <Value<T> as ArgumentType<'_>>::Argument {
82    //     self.0
83    // }
84
85    fn provide_argument_to<
86        Out,
87        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
88    >(
89        &self,
90        f: F,
91    ) -> Out {
92        f(self.0)
93    }
94}
95impl<T: Clone> ProvideArgument for Cloned<T> {
96    type ProvideArgumentType = Value<T>;
97
98    // fn provide_argument(&self) -> <Value<T> as ArgumentType<'_>>::Argument {
99    //     self.0.clone()
100    // }
101
102    fn provide_argument_to<
103        Out,
104        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
105    >(
106        &self,
107        f: F,
108    ) -> Out {
109        f(self.0.clone())
110    }
111}
112
113impl<T> ProvideArgument for Refed<T> {
114    type ProvideArgumentType = ByRef<T>;
115
116    // fn provide_argument(&self) -> &T {
117    //     &self.0
118    // }
119
120    fn provide_argument_to<
121        Out,
122        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
123    >(
124        &self,
125        f: F,
126    ) -> Out {
127        f(&self.0)
128    }
129}
130
131impl<Arg, Cbk: crate::Callable<(), Output = Arg>> ProvideArgument for With<Cbk> {
132    type ProvideArgumentType = Value<Arg>;
133
134    fn provide_argument_to<
135        Out,
136        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
137    >(
138        &self,
139        f: F,
140    ) -> Out {
141        f(self.0.call_fn(()))
142    }
143}
144
145mod last {
146    use super::*;
147
148    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
149    pub struct LastArgumentProvided<
150        F: super::super::CallableWithFixedArguments,
151        A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::Last>,
152    > {
153        pub(crate) f: F,
154        pub(crate) last_argument: A,
155    }
156
157    impl<
158            F: super::super::CallableWithFixedArguments,
159            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::Last>,
160        > crate::IsCallable for LastArgumentProvided<F, A>
161    {
162    }
163
164    // FIXME: Output should be <F as super::Callable<ArgumentsOfTypes<'_, F::FixedArgumentTypes>>>::Output
165    impl<
166            Out,
167            F: super::super::CallableWithFixedArguments<Output = Out>,
168            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::Last>,
169        >
170        crate::Callable<ArgumentsOfTypes<'_, <F::FixedArgumentTypes as ArgumentTypes>::LastTrimmed>>
171        for LastArgumentProvided<F, A>
172    {
173        type Output = Out;
174
175        fn call_fn(
176            &self,
177            args: ArgumentsOfTypes<'_, <F::FixedArgumentTypes as ArgumentTypes>::LastTrimmed>,
178        ) -> Self::Output {
179            self.last_argument
180                .provide_argument_to(move |last| self.f.call_with_appended_args(args, last))
181        }
182    }
183
184    impl<
185            Out,
186            F: super::super::CallableWithFixedArguments<Output = Out>,
187            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::Last>,
188        > crate::CallableWithFixedArguments for LastArgumentProvided<F, A>
189    {
190        type FixedArgumentTypes = <F::FixedArgumentTypes as ArgumentTypes>::LastTrimmed;
191    }
192}
193
194mod first {
195    use super::*;
196
197    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
198    pub struct FirstArgumentProvided<
199        F: super::super::CallableWithFixedArguments,
200        A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::First>,
201    > {
202        pub(crate) f: F,
203        pub(crate) first_argument: A,
204    }
205
206    impl<
207            F: super::super::CallableWithFixedArguments,
208            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::First>,
209        > super::super::IsCallable for FirstArgumentProvided<F, A>
210    {
211    }
212
213    impl<
214            Out,
215            F: super::super::CallableWithFixedArguments<Output = Out>,
216            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::First>,
217        >
218        super::super::Callable<
219            ArgumentsOfTypes<'_, <F::FixedArgumentTypes as ArgumentTypes>::FirstTrimmed>,
220        > for FirstArgumentProvided<F, A>
221    {
222        type Output = Out;
223
224        fn call_fn(
225            &self,
226            args: ArgumentsOfTypes<'_, <F::FixedArgumentTypes as ArgumentTypes>::FirstTrimmed>,
227        ) -> Self::Output {
228            self.first_argument
229                .provide_argument_to(move |first| self.f.call_with_prepended_args(first, args))
230        }
231    }
232
233    impl<
234            Out,
235            F: super::super::CallableWithFixedArguments<Output = Out>,
236            A: ProvideArgument<ProvideArgumentType = <F::FixedArgumentTypes as ArgumentTypes>::First>,
237        > super::super::CallableWithFixedArguments for FirstArgumentProvided<F, A>
238    {
239        type FixedArgumentTypes = <F::FixedArgumentTypes as ArgumentTypes>::FirstTrimmed;
240    }
241}
242
243pub trait Arguments<'a, ImplicitBounds = &'a Self> {
244    type Arguments: super::Tuple;
245}
246
247pub trait PrependArgument<Arg: ArgumentType>: ArgumentTypes {
248    type Prepended: ArgumentTypes<First = Arg, FirstTrimmed = Self>;
249
250    fn prepend_argument<'a>(
251        first: ArgumentOfType<'a, Arg>,
252        args: ArgumentsOfTypes<'a, Self>,
253    ) -> ArgumentsOfTypes<'a, Self::Prepended>;
254}
255
256pub trait AppendArgument<Arg: ArgumentType>: ArgumentTypes {
257    type Appended: ArgumentTypes<Last = Arg, LastTrimmed = Self>;
258
259    fn append_argument<'a>(
260        args: ArgumentsOfTypes<'a, Self>,
261        last: ArgumentOfType<'a, Arg>,
262    ) -> ArgumentsOfTypes<'a, Self::Appended>;
263}
264
265pub trait ArgumentTypes: super::Tuple + for<'a> Arguments<'a> {
266    type First: ArgumentType;
267    type FirstTrimmed: ArgumentTypes + PrependArgument<Self::First, Prepended = Self>;
268
269    type Last: ArgumentType;
270    type LastTrimmed: ArgumentTypes + AppendArgument<Self::Last, Appended = Self>;
271
272    fn re_borrow<'a: 'b, 'b>(args: ArgumentsOfTypes<'a, Self>) -> ArgumentsOfTypes<'b, Self>;
273
274    fn from_prepended<'a>(
275        first: ArgumentOfType<'a, Self::First>,
276        args: ArgumentsOfTypes<'a, Self::FirstTrimmed>,
277    ) -> ArgumentsOfTypes<'a, Self> {
278        <Self::FirstTrimmed as PrependArgument<Self::First>>::prepend_argument(first, args)
279    }
280
281    fn from_appended<'a>(
282        args: ArgumentsOfTypes<'a, Self::LastTrimmed>,
283        last: ArgumentOfType<'a, Self::Last>,
284    ) -> ArgumentsOfTypes<'a, Self> {
285        <Self::LastTrimmed as AppendArgument<Self::Last>>::append_argument(args, last)
286    }
287}
288
289pub type ArgumentOfType<'a, A> = <A as Argument<'a>>::Argument;
290pub type ArgumentsOfTypes<'a, A> = <A as Arguments<'a>>::Arguments;
291
292pub enum Invalid {}
293
294impl<'a> Argument<'a> for Invalid {
295    type Argument = Invalid;
296}
297
298impl ArgumentType for Invalid {
299    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self> {
300        match arg {}
301    }
302}
303
304pub enum InvalidTuple {}
305
306impl super::sealed::Sealed for InvalidTuple {}
307impl super::Tuple for InvalidTuple {}
308
309impl<'a> Arguments<'a> for InvalidTuple {
310    type Arguments = InvalidTuple;
311}
312
313impl ArgumentTypes for InvalidTuple {
314    type First = Invalid2;
315    type FirstTrimmed = InvalidTuple;
316    type Last = Invalid2;
317    type LastTrimmed = InvalidTuple;
318
319    fn re_borrow<'a: 'b, 'b>(args: ArgumentsOfTypes<'a, Self>) -> ArgumentsOfTypes<'b, Self> {
320        match args {}
321    }
322}
323
324impl PrependArgument<Invalid> for InvalidTuple {
325    type Prepended = ();
326
327    fn prepend_argument<'a>(
328        first: ArgumentOfType<'a, Invalid>,
329        _: ArgumentsOfTypes<'a, Self>,
330    ) -> ArgumentsOfTypes<'a, Self::Prepended> {
331        match first {}
332    }
333}
334
335impl PrependArgument<Invalid2> for InvalidTuple {
336    type Prepended = InvalidTuple;
337
338    fn prepend_argument<'a>(
339        first: ArgumentOfType<'a, Invalid2>,
340        _: ArgumentsOfTypes<'a, Self>,
341    ) -> ArgumentsOfTypes<'a, Self::Prepended> {
342        match first {}
343    }
344}
345
346impl AppendArgument<Invalid> for InvalidTuple {
347    type Appended = ();
348
349    fn append_argument<'a>(
350        _: ArgumentsOfTypes<'a, Self>,
351        last: ArgumentOfType<'a, Invalid>,
352    ) -> ArgumentsOfTypes<'a, Self::Appended> {
353        match last {}
354    }
355}
356
357impl AppendArgument<Invalid2> for InvalidTuple {
358    type Appended = InvalidTuple;
359
360    fn append_argument<'a>(
361        _: ArgumentsOfTypes<'a, Self>,
362        last: ArgumentOfType<'a, Invalid2>,
363    ) -> ArgumentsOfTypes<'a, Self::Appended> {
364        match last {}
365    }
366}
367
368pub enum Invalid2 {}
369
370impl<'a> Argument<'a> for Invalid2 {
371    type Argument = Invalid2;
372}
373
374impl ArgumentType for Invalid2 {
375    fn re_borrow<'a: 'b, 'b>(arg: ArgumentOfType<'a, Self>) -> ArgumentOfType<'b, Self> {
376        match arg {}
377    }
378}
379
380impl ProvideArgument for Invalid {
381    type ProvideArgumentType = Invalid;
382
383    // fn provide_argument(&self) -> <Self::ProvideArgumentType as ArgumentType<'_>>::Argument {
384    //     match *self {}
385    // }
386
387    fn provide_argument_to<
388        Out,
389        F: for<'arg> FnOnce(ArgumentOfType<'arg, Self::ProvideArgumentType>) -> Out,
390    >(
391        &self,
392        _: F,
393    ) -> Out {
394        match *self {}
395    }
396}