1use std::{
4 fmt::{self, Display},
5 io::{self, Read},
6 marker::PhantomData,
7 rc::Rc,
8 sync::Arc,
9};
10
11use borsh::{self, BorshDeserialize, BorshSerialize};
12use defuse_io_utils::ReadExt;
13use impl_tools::autoimpl;
14
15#[cfg(feature = "schema")]
16mod schema;
17#[cfg(feature = "schema")]
18pub use self::schema::*;
19
20mod duration;
21pub use self::duration::*;
22
23pub trait BorshSerializeAs<T: ?Sized> {
24 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
25 where
26 W: io::Write;
27}
28
29pub trait BorshDeserializeAs<T> {
30 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
31 where
32 R: io::Read;
33}
34
35pub struct As<T: ?Sized>(PhantomData<T>);
36
37impl<T: ?Sized> As<T> {
38 #[inline]
39 pub fn serialize<U, W>(obj: &U, writer: &mut W) -> io::Result<()>
40 where
41 T: BorshSerializeAs<U>,
42 W: io::Write,
43 U: ?Sized,
44 {
45 T::serialize_as(obj, writer)
46 }
47
48 #[inline]
49 pub fn deserialize<R, U>(reader: &mut R) -> io::Result<U>
50 where
51 T: BorshDeserializeAs<U>,
52 R: io::Read,
53 {
54 T::deserialize_as(reader)
55 }
56}
57
58#[derive(Debug, Eq, PartialEq)]
60pub struct Same;
61
62impl<T> BorshSerializeAs<T> for Same
63where
64 T: BorshSerialize,
65{
66 #[inline]
67 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
68 where
69 W: io::Write,
70 {
71 source.serialize(writer)
72 }
73}
74
75impl<T> BorshDeserializeAs<T> for Same
76where
77 T: BorshDeserialize,
78{
79 #[inline]
80 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
81 where
82 R: io::Read,
83 {
84 T::deserialize_reader(reader)
85 }
86}
87
88#[autoimpl(Deref using self.value)]
91#[autoimpl(DerefMut using self.value)]
92#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
93pub struct AsWrap<T, As: ?Sized> {
94 value: T,
95 _marker: PhantomData<As>,
96}
97
98impl<T, As: ?Sized> AsWrap<T, As> {
99 #[must_use]
100 #[inline]
101 pub const fn new(value: T) -> Self {
102 Self {
103 value,
104 _marker: PhantomData,
105 }
106 }
107
108 #[inline]
110 pub fn into_inner(self) -> T {
111 self.value
112 }
113}
114
115impl<T, As: ?Sized> From<T> for AsWrap<T, As> {
116 #[inline]
117 fn from(value: T) -> Self {
118 Self::new(value)
119 }
120}
121
122pub fn to_vec_as<T, As>(source: &T) -> io::Result<Vec<u8>>
123where
124 As: BorshSerializeAs<T> + ?Sized,
125{
126 borsh::to_vec(&AsWrap::<&T, &As>::new(source))
127}
128
129impl<T, As> BorshDeserialize for AsWrap<T, As>
130where
131 As: BorshDeserializeAs<T> + ?Sized,
132{
133 #[inline]
134 fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
135 As::deserialize_as(reader).map(Self::new)
136 }
137}
138
139impl<T, As> BorshSerialize for AsWrap<T, As>
140where
141 As: BorshSerializeAs<T> + ?Sized,
142{
143 #[inline]
144 fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
145 As::serialize_as(&self.value, writer)
146 }
147}
148
149#[cfg(feature = "schema")]
150const _: () = {
151 use borsh::schema::{Declaration, Definition};
152 use std::collections::BTreeMap;
153
154 impl<T, As> borsh::BorshSchema for AsWrap<T, As>
155 where
156 T: borsh::BorshSchema,
157 As: ?Sized,
158 {
159 fn declaration() -> Declaration {
160 T::declaration()
161 }
162
163 fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
164 T::add_definitions_recursively(definitions);
165 }
166 }
167};
168
169impl<T, As> fmt::Debug for AsWrap<T, As>
170where
171 T: fmt::Debug,
172 As: ?Sized,
173{
174 #[inline]
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 fmt::Debug::fmt(&self.value, f)
177 }
178}
179
180impl<T, As> fmt::Display for AsWrap<T, As>
181where
182 T: fmt::Display,
183 As: ?Sized,
184{
185 #[inline]
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 fmt::Display::fmt(&self.value, f)
188 }
189}
190
191impl<T, As> BorshSerializeAs<&T> for &As
192where
193 T: ?Sized,
194 As: BorshSerializeAs<T> + ?Sized,
195{
196 #[inline]
197 fn serialize_as<W>(source: &&T, writer: &mut W) -> io::Result<()>
198 where
199 W: io::Write,
200 {
201 As::serialize_as(source, writer)
202 }
203}
204
205impl<T, As> BorshSerializeAs<&mut T> for &mut As
206where
207 T: ?Sized,
208 As: BorshSerializeAs<T> + ?Sized,
209{
210 #[inline]
211 fn serialize_as<W>(source: &&mut T, writer: &mut W) -> io::Result<()>
212 where
213 W: io::Write,
214 {
215 As::serialize_as(source, writer)
216 }
217}
218
219impl<T, As> BorshSerializeAs<Option<T>> for Option<As>
220where
221 As: BorshSerializeAs<T>,
222{
223 #[inline]
224 fn serialize_as<W>(source: &Option<T>, writer: &mut W) -> io::Result<()>
225 where
226 W: io::Write,
227 {
228 source
229 .as_ref()
230 .map(AsWrap::<&T, &As>::new)
231 .serialize(writer)
232 }
233}
234
235impl<T, As> BorshDeserializeAs<Option<T>> for Option<As>
236where
237 As: BorshDeserializeAs<T>,
238{
239 #[inline]
240 fn deserialize_as<R>(reader: &mut R) -> io::Result<Option<T>>
241 where
242 R: io::Read,
243 {
244 Ok(Option::<AsWrap<T, As>>::deserialize_reader(reader)?.map(AsWrap::into_inner))
245 }
246}
247
248impl<T, As> BorshSerializeAs<Box<T>> for Box<As>
249where
250 As: BorshSerializeAs<T> + ?Sized,
251{
252 #[inline]
253 fn serialize_as<W>(source: &Box<T>, writer: &mut W) -> io::Result<()>
254 where
255 W: io::Write,
256 {
257 AsWrap::<&T, &As>::new(source).serialize(writer)
258 }
259}
260
261impl<T, As> BorshDeserializeAs<Box<T>> for Box<As>
262where
263 As: BorshDeserializeAs<T> + ?Sized,
264{
265 #[inline]
266 fn deserialize_as<R>(reader: &mut R) -> io::Result<Box<T>>
267 where
268 R: io::Read,
269 {
270 AsWrap::<T, As>::deserialize_reader(reader)
271 .map(AsWrap::into_inner)
272 .map(Box::new)
273 }
274}
275
276impl<T, As> BorshSerializeAs<Rc<T>> for Rc<As>
277where
278 As: BorshSerializeAs<T> + ?Sized,
279{
280 #[inline]
281 fn serialize_as<W>(source: &Rc<T>, writer: &mut W) -> io::Result<()>
282 where
283 W: io::Write,
284 {
285 AsWrap::<&T, &As>::new(source).serialize(writer)
286 }
287}
288
289impl<T, As> BorshDeserializeAs<Rc<T>> for Rc<As>
290where
291 As: BorshDeserializeAs<T> + ?Sized,
292{
293 #[inline]
294 fn deserialize_as<R>(reader: &mut R) -> io::Result<Rc<T>>
295 where
296 R: io::Read,
297 {
298 AsWrap::<T, As>::deserialize_reader(reader)
299 .map(AsWrap::into_inner)
300 .map(Rc::new)
301 }
302}
303
304impl<T, As> BorshSerializeAs<Arc<T>> for Arc<As>
305where
306 As: BorshSerializeAs<T> + ?Sized,
307{
308 #[inline]
309 fn serialize_as<W>(source: &Arc<T>, writer: &mut W) -> io::Result<()>
310 where
311 W: io::Write,
312 {
313 AsWrap::<&T, &As>::new(source).serialize(writer)
314 }
315}
316
317impl<T, As> BorshDeserializeAs<Arc<T>> for Arc<As>
318where
319 As: BorshDeserializeAs<T> + ?Sized,
320{
321 #[inline]
322 fn deserialize_as<R>(reader: &mut R) -> io::Result<Arc<T>>
323 where
324 R: io::Read,
325 {
326 AsWrap::<T, As>::deserialize_reader(reader)
327 .map(AsWrap::into_inner)
328 .map(Arc::new)
329 }
330}
331
332impl<T, As> BorshSerializeAs<[T]> for [As]
333where
334 As: BorshSerializeAs<T>,
335{
336 #[inline]
337 fn serialize_as<W>(source: &[T], writer: &mut W) -> io::Result<()>
338 where
339 W: io::Write,
340 {
341 source.iter().try_for_each(|v| As::serialize_as(v, writer))
342 }
343}
344
345impl<T, As, const N: usize> BorshSerializeAs<[T; N]> for [As; N]
346where
347 As: BorshSerializeAs<T>,
348{
349 #[inline]
350 fn serialize_as<W>(source: &[T; N], writer: &mut W) -> io::Result<()>
351 where
352 W: io::Write,
353 {
354 <&[As]>::serialize_as(&source.as_slice(), writer)
355 }
356}
357
358impl<T, As, const N: usize> BorshDeserializeAs<[T; N]> for [As; N]
359where
360 As: BorshDeserializeAs<T>,
361{
362 #[inline]
363 fn deserialize_as<R>(reader: &mut R) -> io::Result<[T; N]>
364 where
365 R: io::Read,
366 {
367 array_util::try_from_fn(|_i| As::deserialize_as(reader))
369 }
370}
371
372macro_rules! impl_borsh_serde_as_for_tuple {
373 ($($n:tt:$t:ident as $a:ident),+) => {
374 impl<$($t, $a),+> BorshSerializeAs<($($t,)+)> for ($($a,)+)
375 where $(
376 $a: BorshSerializeAs<$t>,
377 )+
378 {
379 #[inline]
380 fn serialize_as<W>(source: &($($t,)+), writer: &mut W) -> io::Result<()>
381 where
382 W: io::Write,
383 {
384 $(
385 $a::serialize_as(&source.$n, writer)?;
386 )+
387 Ok(())
388 }
389 }
390
391 impl<$($t, $a),+> BorshDeserializeAs<($($t,)+)> for ($($a,)+)
392 where $(
393 $a: BorshDeserializeAs<$t>,
394 )+
395 {
396 #[inline]
397 fn deserialize_as<R>(reader: &mut R) -> io::Result<($($t,)+)>
398 where
399 R: io::Read,
400 {
401 Ok(($(
402 $a::deserialize_as(reader)?,
403 )+))
404 }
405 }
406 };
407}
408impl_borsh_serde_as_for_tuple!(0:T0 as As0);
409impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1);
410impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2);
411impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3);
412impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4);
413impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5);
414impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6);
415impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7);
416impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7,8:T8 as As8);
417impl_borsh_serde_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7,8:T8 as As8,9:T9 as As9);
418
419pub struct FromInto<T: ?Sized>(PhantomData<T>);
420
421impl<T, U> BorshSerializeAs<T> for FromInto<U>
422where
423 T: Into<U> + Clone,
424 U: BorshSerialize,
425{
426 #[inline]
427 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
428 where
429 W: io::Write,
430 {
431 source.clone().into().serialize(writer)
432 }
433}
434
435impl<T, U> BorshDeserializeAs<T> for FromInto<U>
436where
437 U: BorshDeserialize + Into<T>,
438{
439 #[inline]
440 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
441 where
442 R: io::Read,
443 {
444 U::deserialize_reader(reader).map(Into::into)
445 }
446}
447
448pub struct FromIntoRef<T: ?Sized>(PhantomData<T>);
449
450impl<T, U> BorshSerializeAs<T> for FromIntoRef<U>
451where
452 for<'a> &'a T: Into<U>,
453 U: BorshSerialize,
454{
455 #[inline]
456 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
457 where
458 W: io::Write,
459 {
460 source.into().serialize(writer)
461 }
462}
463
464impl<T, U> BorshDeserializeAs<T> for FromIntoRef<U>
465where
466 U: BorshDeserialize + Into<T>,
467{
468 #[inline]
469 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
470 where
471 R: io::Read,
472 {
473 U::deserialize_reader(reader).map(Into::into)
474 }
475}
476
477pub struct TryFromInto<T: ?Sized>(PhantomData<T>);
478
479impl<T, U> BorshSerializeAs<T> for TryFromInto<U>
480where
481 T: TryInto<U> + Clone,
482 <T as TryInto<U>>::Error: Display,
483 U: BorshSerialize,
484{
485 #[inline]
486 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
487 where
488 W: io::Write,
489 {
490 source
491 .clone()
492 .try_into()
493 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string()))?
494 .serialize(writer)
495 }
496}
497
498impl<T, U> BorshDeserializeAs<T> for TryFromInto<U>
499where
500 U: BorshDeserialize + TryInto<T>,
501 <U as TryInto<T>>::Error: Display,
502{
503 #[inline]
504 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
505 where
506 R: io::Read,
507 {
508 U::deserialize_reader(reader).and_then(|v| {
509 v.try_into()
510 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string()))
511 })
512 }
513}
514
515pub struct Or<T1: ?Sized, T2: ?Sized>(PhantomData<T1>, PhantomData<T2>);
516
517pub struct Remainder;
535
536impl<T> BorshSerializeAs<T> for Remainder
537where
538 T: AsRef<[u8]>,
539{
540 #[inline]
541 fn serialize_as<W>(source: &T, writer: &mut W) -> io::Result<()>
542 where
543 W: io::Write,
544 {
545 writer.write_all(source.as_ref())
546 }
547}
548
549impl<T> BorshDeserializeAs<T> for Remainder
550where
551 T: TryFrom<Vec<u8>>,
552 T::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
553{
554 #[inline]
555 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
556 where
557 R: io::Read,
558 {
559 let mut buf = Vec::new();
560 reader.read_to_end(&mut buf)?;
561 buf.try_into()
562 .map_err(|err: T::Error| io::Error::new(io::ErrorKind::InvalidData, err))
563 }
564}
565
566impl<T, As1, As2> BorshDeserializeAs<T> for Or<As1, As2>
567where
568 As1: BorshDeserializeAs<T> + ?Sized,
569 As2: BorshDeserializeAs<T> + ?Sized,
570{
571 #[inline]
572 fn deserialize_as<R>(reader: &mut R) -> io::Result<T>
573 where
574 R: io::Read,
575 {
576 let mut buf = Vec::new();
577 As1::deserialize_as(&mut reader.tee(&mut buf))
578 .or_else(|_| As2::deserialize_as(&mut buf.chain(reader)))
579 }
580}
581
582#[cfg(test)]
583mod tests;