1use std::error::Error as StdError;
4use std::fmt;
5use std::marker::PhantomData;
6use std::ops::Deref;
7
8use crate::codec::{Codec, CodecError};
9use crate::error::{OpenError, PushError};
10use crate::queue::{Builder, Consumer, Producer, Reserved};
11use crate::store::Store;
12
13pub type TypedEnds<S, T, C> = (TypedProducer<S, T, C>, TypedConsumer<S, T, C>);
15
16impl<S: Store> Builder<S> {
17 pub fn open_typed<T, C>(self, codec: C) -> Result<TypedEnds<S, T, C>, OpenError<S::Error>>
23 where
24 C: Codec<T> + Clone,
25 {
26 let (producer, consumer) = self.open()?;
27 Ok((
28 TypedProducer {
29 inner: producer,
30 codec: codec.clone(),
31 _marker: PhantomData,
32 },
33 TypedConsumer {
34 inner: consumer,
35 codec,
36 _marker: PhantomData,
37 },
38 ))
39 }
40}
41
42pub struct TypedProducer<S, T, C> {
44 inner: Producer<S>,
45 codec: C,
46 _marker: PhantomData<fn(T)>,
47}
48
49impl<S, T, C: Clone> Clone for TypedProducer<S, T, C> {
50 fn clone(&self) -> Self {
51 Self {
52 inner: self.inner.clone(),
53 codec: self.codec.clone(),
54 _marker: PhantomData,
55 }
56 }
57}
58
59impl<S: Store, T, C: Codec<T>> TypedProducer<S, T, C> {
60 pub fn push(&self, value: &T) -> Result<(), TypedPushError<S::Error>> {
62 let bytes = self.codec.encode(value).map_err(TypedPushError::Encode)?;
63 self.inner.push(&bytes).map_err(|e| match e {
64 PushError::Closed => TypedPushError::Closed,
65 PushError::Store(e) => TypedPushError::Store(e),
66 })
67 }
68
69 pub fn close(&self) {
71 self.inner.close();
72 }
73
74 pub fn len(&self) -> usize {
76 self.inner.len()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.inner.is_empty()
82 }
83}
84
85pub struct TypedConsumer<S, T, C> {
87 inner: Consumer<S>,
88 codec: C,
89 _marker: PhantomData<fn() -> T>,
90}
91
92impl<S: Store, T, C: Codec<T>> TypedConsumer<S, T, C> {
93 pub fn reserve(&self) -> Result<Option<TypedReserved<S, T>>, ReserveError<S::Error>> {
95 match self.inner.reserve().map_err(ReserveError::Store)? {
96 Some(reserved) => {
97 let value = self.codec.decode(&reserved).map_err(ReserveError::Decode)?;
98 Ok(Some(TypedReserved {
99 inner: reserved,
100 value,
101 }))
102 }
103 None => Ok(None),
104 }
105 }
106}
107
108pub struct TypedReserved<S: Store, T> {
111 inner: Reserved<S>,
112 value: T,
113}
114
115impl<S: Store, T> TypedReserved<S, T> {
116 pub fn seq(&self) -> u64 {
118 self.inner.seq()
119 }
120
121 pub fn ack(self) -> Result<(), S::Error> {
123 self.inner.ack()
124 }
125
126 pub fn nack(self) {
128 self.inner.nack();
129 }
130}
131
132impl<S: Store, T> Deref for TypedReserved<S, T> {
133 type Target = T;
134 fn deref(&self) -> &T {
135 &self.value
136 }
137}
138
139#[derive(Debug)]
141pub enum TypedPushError<E> {
142 Encode(CodecError),
144 Closed,
146 Store(E),
148}
149
150impl<E: fmt::Display> fmt::Display for TypedPushError<E> {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 match self {
153 TypedPushError::Encode(e) => write!(f, "{e}"),
154 TypedPushError::Closed => write!(f, "queue is closed"),
155 TypedPushError::Store(e) => write!(f, "store error: {e}"),
156 }
157 }
158}
159
160impl<E: StdError + 'static> StdError for TypedPushError<E> {
161 fn source(&self) -> Option<&(dyn StdError + 'static)> {
162 match self {
163 TypedPushError::Encode(e) => Some(e),
164 TypedPushError::Store(e) => Some(e),
165 TypedPushError::Closed => None,
166 }
167 }
168}
169
170#[derive(Debug)]
172pub enum ReserveError<E> {
173 Store(E),
175 Decode(CodecError),
177}
178
179impl<E: fmt::Display> fmt::Display for ReserveError<E> {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 match self {
182 ReserveError::Store(e) => write!(f, "store error: {e}"),
183 ReserveError::Decode(e) => write!(f, "{e}"),
184 }
185 }
186}
187
188impl<E: StdError + 'static> StdError for ReserveError<E> {
189 fn source(&self) -> Option<&(dyn StdError + 'static)> {
190 match self {
191 ReserveError::Store(e) => Some(e),
192 ReserveError::Decode(e) => Some(e),
193 }
194 }
195}