1use std::collections::BTreeMap;
18use std::collections::BTreeSet;
19use std::fmt::Debug;
20use std::marker::PhantomData;
21
22use crate::metadata::ThriftAnnotations;
23
24pub trait ThriftAdapter {
25 type StandardType;
27 type AdaptedType: Clone + Debug + PartialEq + Send + Sync;
29
30 type Error: Into<anyhow::Error> + Debug;
32
33 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error>;
37
38 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType;
52
53 fn from_thrift_field<T: ThriftAnnotations>(
59 value: Self::StandardType,
60 _field_id: i16,
61 ) -> Result<Self::AdaptedType, Self::Error> {
62 Self::from_thrift(value)
63 }
64
65 fn to_thrift_field<T: ThriftAnnotations>(
71 value: &Self::AdaptedType,
72 _field_id: i16,
73 ) -> Self::StandardType {
74 Self::to_thrift(value)
75 }
76
77 fn from_thrift_default<T: ThriftAnnotations>(
88 value: Self::StandardType,
89 field_id: i16,
90 ) -> Self::AdaptedType {
91 Self::from_thrift_field::<T>(value, field_id).unwrap_or_else(|e| {
92 panic!(
93 "`from_thrift_field` must not return an `Err` on field ID {} for its default value, but it did: '{:?}'",
94 field_id, e
95 );
96 })
97 }
98}
99
100pub struct LayeredThriftAdapter<Fst, Snd>
106where
107 Fst: ThriftAdapter,
108 Snd: ThriftAdapter,
109 Fst::StandardType: Into<Snd::AdaptedType>,
110 Snd::AdaptedType: Into<Fst::StandardType>,
111{
112 _inner_first: PhantomData<Fst>,
113 _inner_second: PhantomData<Snd>,
114}
115
116impl<Fst, Snd> ThriftAdapter for LayeredThriftAdapter<Fst, Snd>
117where
118 Fst: ThriftAdapter,
119 Snd: ThriftAdapter,
120 Fst::StandardType: Into<Snd::AdaptedType>,
121 Snd::AdaptedType: Into<Fst::StandardType>,
122{
123 type StandardType = <Snd as ThriftAdapter>::StandardType;
124 type AdaptedType = <Fst as ThriftAdapter>::AdaptedType;
125
126 type Error = anyhow::Error;
127
128 #[inline]
129 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
130 <Fst as ThriftAdapter>::from_thrift(
131 <Snd as ThriftAdapter>::from_thrift(value)
132 .map_err(Into::<anyhow::Error>::into)?
133 .into(),
134 )
135 .map_err(Into::<anyhow::Error>::into)
136 }
137
138 #[inline]
139 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
140 <Snd as ThriftAdapter>::to_thrift(&<Fst as ThriftAdapter>::to_thrift(value).into())
141 }
142
143 #[inline]
144 fn from_thrift_field<T: ThriftAnnotations>(
145 value: Self::StandardType,
146 field_id: i16,
147 ) -> Result<Self::AdaptedType, Self::Error> {
148 <Fst as ThriftAdapter>::from_thrift_field::<T>(
149 <Snd as ThriftAdapter>::from_thrift_field::<T>(value, field_id)
150 .map_err(Into::<anyhow::Error>::into)?
151 .into(),
152 field_id,
153 )
154 .map_err(Into::<anyhow::Error>::into)
155 }
156
157 #[inline]
158 fn to_thrift_field<T: ThriftAnnotations>(
159 value: &Self::AdaptedType,
160 field_id: i16,
161 ) -> Self::StandardType {
162 <Snd as ThriftAdapter>::to_thrift_field::<T>(
163 &<Fst as ThriftAdapter>::to_thrift_field::<T>(value, field_id).into(),
164 field_id,
165 )
166 }
167
168 #[inline]
169 fn from_thrift_default<T: ThriftAnnotations>(
170 value: Self::StandardType,
171 field_id: i16,
172 ) -> Self::AdaptedType {
173 <Fst as ThriftAdapter>::from_thrift_default::<T>(
174 <Snd as ThriftAdapter>::from_thrift_default::<T>(value, field_id).into(),
175 field_id,
176 )
177 }
178}
179
180pub struct ListMapAdapter<A>
184where
185 A: ThriftAdapter,
186{
187 _inner_adapter: PhantomData<A>,
188}
189
190impl<A> ThriftAdapter for ListMapAdapter<A>
191where
192 A: ThriftAdapter,
193{
194 type StandardType = Vec<A::StandardType>;
195 type AdaptedType = Vec<A::AdaptedType>;
196
197 type Error = A::Error;
198
199 #[inline]
200 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
201 value
202 .into_iter()
203 .map(|elem| A::from_thrift(elem))
204 .collect::<Result<Self::AdaptedType, Self::Error>>()
205 }
206
207 #[inline]
208 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
209 value.iter().map(|elem| A::to_thrift(elem)).collect()
210 }
211
212 #[inline]
213 fn from_thrift_field<T: ThriftAnnotations>(
214 value: Self::StandardType,
215 field_id: i16,
216 ) -> Result<Self::AdaptedType, Self::Error> {
217 value
218 .into_iter()
219 .map(|elem| A::from_thrift_field::<T>(elem, field_id))
220 .collect::<Result<Self::AdaptedType, Self::Error>>()
221 }
222
223 #[inline]
224 fn to_thrift_field<T: ThriftAnnotations>(
225 value: &Self::AdaptedType,
226 field_id: i16,
227 ) -> Self::StandardType {
228 value
229 .iter()
230 .map(|elem| A::to_thrift_field::<T>(elem, field_id))
231 .collect()
232 }
233
234 #[inline]
235 fn from_thrift_default<T: ThriftAnnotations>(
236 value: Self::StandardType,
237 field_id: i16,
238 ) -> Self::AdaptedType {
239 value
240 .into_iter()
241 .map(|elem| A::from_thrift_default::<T>(elem, field_id))
242 .collect()
243 }
244}
245
246pub struct SetMapAdapter<A>
250where
251 A: ThriftAdapter,
252 A::StandardType: Ord + PartialEq,
253 A::AdaptedType: Ord + PartialEq,
254{
255 _inner_adapter: PhantomData<A>,
256}
257
258impl<A> ThriftAdapter for SetMapAdapter<A>
259where
260 A: ThriftAdapter,
261 A::StandardType: Ord + PartialEq,
262 A::AdaptedType: Ord + PartialEq,
263{
264 type StandardType = BTreeSet<A::StandardType>;
265 type AdaptedType = BTreeSet<A::AdaptedType>;
266
267 type Error = A::Error;
268
269 #[inline]
270 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
271 value
272 .into_iter()
273 .map(|elem| A::from_thrift(elem))
274 .collect::<Result<Self::AdaptedType, Self::Error>>()
275 }
276
277 #[inline]
278 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
279 value.iter().map(|elem| A::to_thrift(elem)).collect()
280 }
281
282 #[inline]
283 fn from_thrift_field<T: ThriftAnnotations>(
284 value: Self::StandardType,
285 field_id: i16,
286 ) -> Result<Self::AdaptedType, Self::Error> {
287 value
288 .into_iter()
289 .map(|elem| A::from_thrift_field::<T>(elem, field_id))
290 .collect::<Result<Self::AdaptedType, Self::Error>>()
291 }
292
293 #[inline]
294 fn to_thrift_field<T: ThriftAnnotations>(
295 value: &Self::AdaptedType,
296 field_id: i16,
297 ) -> Self::StandardType {
298 value
299 .iter()
300 .map(|elem| A::to_thrift_field::<T>(elem, field_id))
301 .collect()
302 }
303
304 #[inline]
305 fn from_thrift_default<T: ThriftAnnotations>(
306 value: Self::StandardType,
307 field_id: i16,
308 ) -> Self::AdaptedType {
309 value
310 .into_iter()
311 .map(|elem| A::from_thrift_default::<T>(elem, field_id))
312 .collect()
313 }
314}
315
316pub struct MapMapAdapter<KA, KV>
320where
321 KA: ThriftAdapter,
322 KV: ThriftAdapter,
323 KA::StandardType: Ord + PartialEq,
324 KA::AdaptedType: Ord + PartialEq,
325{
326 _inner_key_adapter: PhantomData<KA>,
327 _inner_val_adapter: PhantomData<KV>,
328}
329
330impl<KA, KV> ThriftAdapter for MapMapAdapter<KA, KV>
331where
332 KA: ThriftAdapter,
333 KV: ThriftAdapter,
334 KA::StandardType: Ord + PartialEq,
335 KA::AdaptedType: Ord + PartialEq,
336{
337 type StandardType = BTreeMap<KA::StandardType, KV::StandardType>;
338 type AdaptedType = BTreeMap<KA::AdaptedType, KV::AdaptedType>;
339
340 type Error = anyhow::Error;
341
342 #[inline]
343 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
344 value
345 .into_iter()
346 .map(|(key, val)| {
347 Ok((
348 KA::from_thrift(key).map_err(Into::<anyhow::Error>::into)?,
349 KV::from_thrift(val).map_err(Into::<anyhow::Error>::into)?,
350 ))
351 })
352 .collect::<Result<Self::AdaptedType, Self::Error>>()
353 }
354
355 #[inline]
356 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
357 value
358 .iter()
359 .map(|(key, val)| (KA::to_thrift(key), KV::to_thrift(val)))
360 .collect::<Self::StandardType>()
361 }
362
363 #[inline]
364 fn from_thrift_field<T: ThriftAnnotations>(
365 value: Self::StandardType,
366 field_id: i16,
367 ) -> Result<Self::AdaptedType, Self::Error> {
368 value
369 .into_iter()
370 .map(|(key, val)| {
371 Ok((
372 KA::from_thrift_field::<T>(key, field_id)
373 .map_err(Into::<anyhow::Error>::into)?,
374 KV::from_thrift_field::<T>(val, field_id)
375 .map_err(Into::<anyhow::Error>::into)?,
376 ))
377 })
378 .collect::<Result<Self::AdaptedType, Self::Error>>()
379 }
380
381 #[inline]
382 fn to_thrift_field<T: ThriftAnnotations>(
383 value: &Self::AdaptedType,
384 field_id: i16,
385 ) -> Self::StandardType {
386 value
387 .iter()
388 .map(|(key, val)| {
389 (
390 KA::to_thrift_field::<T>(key, field_id),
391 KV::to_thrift_field::<T>(val, field_id),
392 )
393 })
394 .collect::<Self::StandardType>()
395 }
396
397 #[inline]
398 fn from_thrift_default<T: ThriftAnnotations>(
399 value: Self::StandardType,
400 field_id: i16,
401 ) -> Self::AdaptedType {
402 value
403 .into_iter()
404 .map(|(key, val)| {
405 (
406 KA::from_thrift_default::<T>(key, field_id),
407 KV::from_thrift_default::<T>(val, field_id),
408 )
409 })
410 .collect::<Self::AdaptedType>()
411 }
412}
413
414pub struct IdentityAdapter<T>
416where
417 T: Clone + Debug + Send + Sync + PartialEq,
418{
419 _inner: PhantomData<T>,
420}
421
422impl<T> ThriftAdapter for IdentityAdapter<T>
423where
424 T: Clone + Debug + Send + Sync + PartialEq,
425{
426 type StandardType = T;
427 type AdaptedType = T;
428
429 type Error = std::convert::Infallible;
430
431 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
432 Ok(value)
433 }
434
435 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
436 value.clone()
437 }
438}
439
440pub trait NewTypeAdapter {
471 type StandardType;
473 type AdaptedType;
475}
476
477impl<Adapter, StandardType, AdaptedType> ThriftAdapter for Adapter
478where
479 Adapter: NewTypeAdapter<StandardType = StandardType, AdaptedType = AdaptedType>,
480 AdaptedType: From<StandardType> + Into<StandardType> + Clone + Debug + Send + Sync + PartialEq,
481{
482 type StandardType = <Self as NewTypeAdapter>::StandardType;
483 type AdaptedType = <Self as NewTypeAdapter>::AdaptedType;
484
485 type Error = <Self::AdaptedType as TryFrom<Self::StandardType>>::Error;
486
487 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
488 value.clone().into()
489 }
490
491 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
492 Self::AdaptedType::try_from(value)
493 }
494}
495
496#[cfg(test)]
497mod tests {
498 use std::any::TypeId;
499
500 use super::*;
501
502 struct DummyParentStruct {}
506
507 impl ThriftAnnotations for DummyParentStruct {}
508
509 struct BoolToStringAdapter {}
510
511 impl ThriftAdapter for BoolToStringAdapter {
512 type StandardType = bool;
513 type AdaptedType = String;
514
515 type Error = anyhow::Error;
516
517 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
518 Ok(value.to_string())
519 }
520
521 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
522 value == "true"
523 }
524
525 fn from_thrift_field<T: ThriftAnnotations>(
526 value: Self::StandardType,
527 field_id: i16,
528 ) -> Result<Self::AdaptedType, Self::Error> {
529 assert_eq!(field_id, 42);
530 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
531
532 Self::from_thrift(value)
533 }
534
535 fn to_thrift_field<T: ThriftAnnotations>(
536 value: &Self::AdaptedType,
537 field_id: i16,
538 ) -> Self::StandardType {
539 assert_eq!(field_id, 42);
540 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
541
542 Self::to_thrift(value)
543 }
544
545 fn from_thrift_default<T: ThriftAnnotations>(
546 value: Self::StandardType,
547 field_id: i16,
548 ) -> Self::AdaptedType {
549 assert_eq!(field_id, 42);
550 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
551
552 Self::from_thrift_field::<T>(value, field_id).unwrap()
553 }
554 }
555
556 struct I64ToBoolAdapter {}
557
558 impl ThriftAdapter for I64ToBoolAdapter {
559 type StandardType = i64;
560 type AdaptedType = bool;
561
562 type Error = anyhow::Error;
563
564 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
565 match value {
566 0 => Ok(false),
567 1 => Ok(true),
568 other => anyhow::bail!("invalid num {}", other),
569 }
570 }
571
572 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
573 if *value { 1 } else { 0 }
574 }
575
576 fn from_thrift_field<T: ThriftAnnotations>(
577 value: Self::StandardType,
578 field_id: i16,
579 ) -> Result<Self::AdaptedType, Self::Error> {
580 assert_eq!(field_id, 42);
581 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
582
583 Self::from_thrift(value)
584 }
585
586 fn to_thrift_field<T: ThriftAnnotations>(
587 value: &Self::AdaptedType,
588 field_id: i16,
589 ) -> Self::StandardType {
590 assert_eq!(field_id, 42);
591 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
592
593 Self::to_thrift(value)
594 }
595
596 fn from_thrift_default<T: ThriftAnnotations>(
597 value: Self::StandardType,
598 field_id: i16,
599 ) -> Self::AdaptedType {
600 assert_eq!(field_id, 42);
601 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
602
603 Self::from_thrift_field::<T>(value, field_id).unwrap()
604 }
605 }
606
607 struct I8ToI64Adapter {}
608
609 impl ThriftAdapter for I8ToI64Adapter {
610 type StandardType = i8;
611 type AdaptedType = i64;
612
613 type Error = anyhow::Error;
614
615 fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
616 Ok(value.into())
617 }
618
619 fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
620 (*value).try_into().unwrap()
621 }
622
623 fn from_thrift_field<T: ThriftAnnotations>(
624 value: Self::StandardType,
625 field_id: i16,
626 ) -> Result<Self::AdaptedType, Self::Error> {
627 assert_eq!(field_id, 42);
628 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
629
630 Self::from_thrift(value)
631 }
632
633 fn to_thrift_field<T: ThriftAnnotations>(
634 value: &Self::AdaptedType,
635 field_id: i16,
636 ) -> Self::StandardType {
637 assert_eq!(field_id, 42);
638 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
639
640 Self::to_thrift(value)
641 }
642
643 fn from_thrift_default<T: ThriftAnnotations>(
644 value: Self::StandardType,
645 field_id: i16,
646 ) -> Self::AdaptedType {
647 assert_eq!(field_id, 42);
648 assert_eq!(TypeId::of::<DummyParentStruct>(), TypeId::of::<T>());
649
650 Self::from_thrift_field::<T>(value, field_id).unwrap()
651 }
652 }
653
654 type TestLayeredAdapter = LayeredThriftAdapter<
655 BoolToStringAdapter,
656 LayeredThriftAdapter<I64ToBoolAdapter, I8ToI64Adapter>,
657 >;
658
659 #[test]
660 fn test_from_thrift() {
661 assert_eq!(TestLayeredAdapter::from_thrift(0_i8).unwrap(), "false");
662 assert_eq!(TestLayeredAdapter::from_thrift(1_i8).unwrap(), "true");
663 }
664
665 #[test]
666 fn test_from_thrift_error() {
667 let res = TestLayeredAdapter::from_thrift(3_i8);
668
669 assert!(res.is_err());
670 assert_eq!(res.unwrap_err().to_string(), "invalid num 3");
671 }
672
673 #[test]
674 fn test_to_thrift() {
675 assert_eq!(TestLayeredAdapter::to_thrift(&"false".to_string()), 0_i8);
676 assert_eq!(TestLayeredAdapter::to_thrift(&"true".to_string()), 1_i8);
677 }
678
679 #[test]
680 fn test_thrift_field() {
681 assert_eq!(
682 TestLayeredAdapter::from_thrift_field::<DummyParentStruct>(0_i8, 42).unwrap(),
683 "false"
684 );
685 assert_eq!(
686 TestLayeredAdapter::from_thrift_default::<DummyParentStruct>(0_i8, 42),
687 "false"
688 );
689 assert_eq!(
690 TestLayeredAdapter::to_thrift_field::<DummyParentStruct>(&"false".to_string(), 42),
691 0_i8
692 );
693 }
694}