Skip to content

Commit

Permalink
Merge pull request #287 from palantir/alias-impls
Browse files Browse the repository at this point in the history
Implement FromIterator and From for aliases
  • Loading branch information
sfackler committed Feb 5, 2024
2 parents 0806f62 + aff7a3f commit cfb7735
Show file tree
Hide file tree
Showing 43 changed files with 328 additions and 2 deletions.
6 changes: 6 additions & 0 deletions changelog/@unreleased/pr-287.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type: feature
feature:
description: Aliases now implement `From<T>` where `T` is their fully-dealiased
type, and `FromIterator` when the aliased type does.
links:
- https://github.com/palantir/conjure-rust/pull/287
25 changes: 25 additions & 0 deletions conjure-codegen/src/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ pub fn generate(ctx: &Context, def: &AliasDefinition) -> TokenStream {
quote!()
};

let from_iterator = match ctx.is_from_iter(def.type_name(), def.alias()) {
Some(item) => quote! {
impl std::iter::FromIterator<#item> for #name {
fn from_iter<T>(iter: T) -> Self
where
T: std::iter::IntoIterator<Item = #item>,
{
#name(std::iter::FromIterator::from_iter(iter))
}
}
},
None => quote!(),
};

let dealiased_type = ctx.rust_type(def.type_name(), ctx.dealiased_type(def.alias()));

quote! {
use conjure_object::serde::{ser, de};

Expand All @@ -101,6 +117,15 @@ pub fn generate(ctx: &Context, def: &AliasDefinition) -> TokenStream {

#plain

#from_iterator

impl std::convert::From<#dealiased_type> for #name {
#[inline]
fn from(v: #dealiased_type) -> Self {
#name(std::convert::From::from(v))
}
}

impl std::ops::Deref for #name {
type Target = #alias;

Expand Down
39 changes: 39 additions & 0 deletions conjure-codegen/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,45 @@ impl Context {
}
}

pub fn is_from_iter(&self, this_type: &TypeName, def: &Type) -> Option<TokenStream> {
match def {
Type::Primitive(_) | Type::Optional(_) => None,
Type::Map(def) => {
let key = self.rust_type(this_type, def.key_type());
let value = self.rust_type(this_type, def.value_type());
Some(quote!((#key, #value)))
}
Type::List(def) => Some(self.rust_type(this_type, def.item_type())),
Type::Set(def) => Some(self.rust_type(this_type, def.item_type())),
Type::Reference(def) => self.ref_is_from_iter(this_type, def),
Type::External(def) => self.is_from_iter(this_type, def.fallback()),
}
}

fn ref_is_from_iter(&self, this_type: &TypeName, name: &TypeName) -> Option<TokenStream> {
match &self.types[name].def {
TypeDefinition::Alias(def) => self.is_from_iter(this_type, def.alias()),
TypeDefinition::Enum(_) | TypeDefinition::Object(_) | TypeDefinition::Union(_) => None,
}
}

pub fn dealiased_type<'a>(&'a self, def: &'a Type) -> &'a Type {
match def {
Type::Primitive(_)
| Type::Optional(_)
| Type::List(_)
| Type::Set(_)
| Type::Map(_) => def,
Type::Reference(name) => match &self.types[name].def {
TypeDefinition::Enum(_) | TypeDefinition::Object(_) | TypeDefinition::Union(_) => {
def
}
TypeDefinition::Alias(def) => self.dealiased_type(def.alias()),
},
Type::External(def) => self.dealiased_type(def.fallback()),
}
}

pub fn rust_type(&self, this_type: &TypeName, def: &Type) -> TokenStream {
self.rust_type_inner(this_type, def, false)
}
Expand Down
6 changes: 6 additions & 0 deletions conjure-codegen/src/example_types/product/aliased_binary.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions conjure-codegen/src/example_types/product/aliased_string.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions conjure-codegen/src/example_types/product/map_alias_example.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions conjure-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@
//! ```
//!
//! The generated structs implement `Deref`, `DerefMut`, `Debug`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord`,
//! `Hash`, `Serialize`, and `Deserialize`. They also implement `Copy` if they wrap a copyable primitive type, `Default`
//! if they wrap a type implementing `Default`, and `Display` if they wrap a type implementing `Display`.
//! `Hash`, `Serialize`, and `Deserialize`. They implement `Copy` if they wrap a copyable primitive type, `Default`
//! if they wrap a type implementing `Default`, `FromIterator` if they wrap a type implementing `FromIterator`, and
//! `Display` if they wrap a type implementing `Display`. They also implement `From<T>`, where `T` is the fully
//! de-aliased inner type.
//!
//! ## Errors
//!
Expand Down
6 changes: 6 additions & 0 deletions conjure-codegen/src/types/argument_name.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions conjure-codegen/src/types/documentation.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions conjure-codegen/src/types/endpoint_name.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions conjure-codegen/src/types/error_namespace.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions conjure-codegen/src/types/field_name.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cfb7735

Please sign in to comment.