Skip to content

Commit

Permalink
Define ArcAdapter<T> to allow values of map/set/list to be wrapped in…
Browse files Browse the repository at this point in the history
… Arc

Summary:
^

Let's assume that I have a thrift spec like
```
struct LargeContent {
    // Many many fields in here
}

struct Structure {
  1: map<string, LargeContent> mapping;
}
```

With the default support offered by thrift we cannot mapping as `BTreeMap<String, Arc<LargeContent>>`.
This is due to the fact that `rust.Arc` annotation can only be applied to fields and not to part of fields.
Using `rust.Type` (and typedef) to alter the type of the map value is not functional either.

Without this diff we could achieve a similar goal by defining an additional thrift struct having a single field like
```
struct LargeContentArc {
    rust.Arc
    1: LargeContent inner;
}
```

This could be functional, but it does require an extra type to be defined that could be not needed in other languages (e.g. Python).
By defining the typedef as alias with an adapter we are able to alter the definition for rust code only and be a no-op type of change for other languages.

Differential Revision: D62230171

fbshipit-source-id: 03b20cbc2735b3923ea1f2a7261f6bb873a64103
  • Loading branch information
macisamuele authored and facebook-github-bot committed Sep 6, 2024
1 parent 1bde66b commit 4db19a9
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
82 changes: 82 additions & 0 deletions shed/fbthrift_ext/adapters/arc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under both the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree and the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree.
*/

//! Adapters that interpret thrift types as [`Ipv4Addr`]s.
use std::marker::PhantomData;
use std::sync::Arc;

use fbthrift::adapter::ThriftAdapter;

/// Adapts a type as [`Arc`]s.
///
/// For more information, see implementation documentation.
///
/// # How is this different from `@rust.Arc` annotation?
/// Annotations are only possible for fields, but if we are interested
/// in having a map/list/set value to be an `Arc`, we need to wrap it
/// into an new thrift type such that we can annotate it.
/// Via the adapter we remove the need of defining a new thrift type
/// which could be not relevant for other languages.
pub struct ArcAdapter<T> {
inner: PhantomData<T>,
}

/// Implementation to wrap a type into Arc.
///
/// This adapter can perform round-trip serialization and deserialization
/// without transforming data for all non-empty inputs.
///
/// # Examples
///
/// ```thrift
/// include "thrift/annotation/rust.thrift";
///
/// @rust.Adapter{name = "::fbthrift_adapters::ArcAdapter<>"}
/// typedef string ArcString;
///
/// struct CreateWorkflowRequest {
/// 1: ArcString target;
/// }
/// ```
impl<T: Clone + std::fmt::Debug + PartialEq + Send + Sync> ThriftAdapter for ArcAdapter<T> {
type StandardType = T;
type AdaptedType = Arc<T>;

type Error = std::convert::Infallible;

fn to_thrift(value: &Self::AdaptedType) -> Self::StandardType {
value.as_ref().clone()
}

fn from_thrift(value: Self::StandardType) -> Result<Self::AdaptedType, Self::Error> {
Ok(value.into())
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn round_trip_string() {
let value = "127.0.0.1".to_owned();
let adapted: Arc<String> = ArcAdapter::from_thrift(value.clone()).unwrap();
let thrift: String = ArcAdapter::to_thrift(&adapted);
assert_eq!(thrift, value);
}

#[test]
fn round_trip_integer() {
let value: u32 = 123;
let adapted: Arc<u32> = ArcAdapter::from_thrift(value).unwrap();
let thrift: u32 = ArcAdapter::to_thrift(&adapted);
assert_eq!(thrift, value);
}
}
3 changes: 3 additions & 0 deletions shed/fbthrift_ext/adapters/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
//!
//! All adapters are re-exported at the root level for easy usage in thrift.
pub mod arc;
pub mod chrono;
pub mod duration;
pub mod ipv4;
Expand All @@ -95,6 +96,8 @@ pub mod socket_addr;
pub mod unsigned_int;
pub mod uuid;

#[doc(inline)]
pub use crate::arc::ArcAdapter;
#[doc(inline)]
pub use crate::duration::*;
#[doc(inline)]
Expand Down

0 comments on commit 4db19a9

Please sign in to comment.