You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.9 KiB

  1. use std::future::Future;
  2. #[async_trait::async_trait]
  3. pub trait ItemAction {
  4. type Input;
  5. type Output;
  6. type Start;
  7. type Error;
  8. async fn action(&self, s: Self::Start, i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error>;
  9. async fn commit(&self, v: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error>;
  10. }
  11. pub struct ItemStateAction<T, S, E> {
  12. _t: std::marker::PhantomData<T>,
  13. _s: std::marker::PhantomData<S>,
  14. _e: std::marker::PhantomData<E>,
  15. }
  16. impl<T, S, E> Default for ItemStateAction<T, S, E> {
  17. fn default() -> ItemStateAction<T, S, E> {
  18. ItemStateAction {
  19. _t: std::marker::PhantomData,
  20. _s: std::marker::PhantomData,
  21. _e: std::marker::PhantomData,
  22. }
  23. }
  24. }
  25. impl<T, S, E> ItemStateAction<T, S, E>
  26. where
  27. T: Send + Sync,
  28. S: Send + Sync,
  29. E: Send + Sync,
  30. {
  31. pub fn act<'a, O, F, Fut>(self, f: F) -> ItemActionStage<'a, O, ItemStateAction<T, S, E>, F, Fut, S, E>
  32. where
  33. F: Fn(S, ()) -> Fut + Send + Sync + 'a,
  34. Fut: Future<Output=Result<(S, O), E>> + Send + 'a
  35. {
  36. ItemActionStage {
  37. _s: Default::default(),
  38. _e: std::marker::PhantomData,
  39. _a: Default::default(),
  40. prev: self,
  41. actionf: f,
  42. }
  43. }
  44. }
  45. pub struct ItemActionStage<'a, O, P, F, Fut, S, E>
  46. where
  47. P: ItemAction,
  48. F: Fn(S, P::Output) -> Fut + Send + Sync + 'a,
  49. Fut: Future<Output=Result<(S, O) , E>> + Send + 'a,
  50. {
  51. _s: std::marker::PhantomData<S>,
  52. _e: std::marker::PhantomData<E>,
  53. _a: std::marker::PhantomData<&'a ()>,
  54. prev: P,
  55. actionf: F,
  56. }
  57. #[async_trait::async_trait]
  58. impl<'a, O, P: ItemAction, F, Fut, S, E> ItemAction for ItemActionStage<'a, O, P, F, Fut, S, E>
  59. where
  60. P: ItemAction + ItemAction<Start = S, Error = E> + Send + Sync,
  61. F: Fn(S, P::Output) -> Fut + Send + Sync + 'a,
  62. Fut: Future<Output=Result<(S, O), E>> + Send + 'a,
  63. S: Send + Sync,
  64. P::Output: Send + Sync,
  65. E: Send + Sync,
  66. O: Send + Sync,
  67. P::Error: Send + Sync,
  68. {
  69. type Input = P::Output;
  70. type Output = O;
  71. type Start = S;
  72. type Error = P::Error;
  73. async fn action(&self, s: Self::Start, i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error> {
  74. (self.actionf)(s, i).await
  75. }
  76. async fn commit(&self, i: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error> {
  77. let (i, prev) = self.prev.commit(i).await?;
  78. self.action(i, prev).await
  79. }
  80. }
  81. impl<'a, O, P: ItemAction, F, Fut, S, E> ItemActionStage<'a, O, P, F, Fut, S, E>
  82. where
  83. P: ItemAction<Start = S, Error = E> + Send + Sync,
  84. F: Fn(S, P::Output) -> Fut + Send + Sync + 'a,
  85. Fut: Future<Output=Result<(S, O), E>> + Send + 'a,
  86. S: Send + Sync,
  87. P::Output: Send + Sync,
  88. E: Send + Sync,
  89. O: Send + Sync,
  90. P::Error: Send + Sync,
  91. {
  92. #[allow(clippy::type_complexity)]
  93. pub fn act<'b, O2, G, GFut>(self, g: G) -> ItemActionStage<'b, O2, ItemActionStage<'a, O, P, F, Fut, S, E>, G, GFut, S, E>
  94. where
  95. S: Send + Sync,
  96. G: Fn(S, <ItemActionStage<'a, O, P, F, Fut, S, E> as ItemAction>::Output) -> GFut + Send + Sync + 'b,
  97. GFut: Future<Output=Result<(S, O2), E>> + Send + 'b,
  98. O2: Send + Sync,
  99. {
  100. ItemActionStage {
  101. _s: Default::default(),
  102. _e: Default::default(),
  103. _a: Default::default(),
  104. prev: self,
  105. actionf: g,
  106. }
  107. }
  108. }
  109. #[async_trait::async_trait]
  110. impl<T, S, E> ItemAction for ItemStateAction<T, S, E>
  111. where
  112. T: Send + Sync,
  113. S: Send + Sync,
  114. E: Send + Sync,
  115. {
  116. type Input = T;
  117. type Output = ();
  118. type Start = T;
  119. type Error = E;
  120. async fn action(&self, s: Self::Start, _i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error> {
  121. Ok((s, ()))
  122. }
  123. async fn commit(&self, i: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error> {
  124. Ok((i, ()))
  125. }
  126. }