Skip to content

Commit 5af572e

Browse files
committed
Reduce allocations
1 parent e565732 commit 5af572e

20 files changed

+617
-501
lines changed

graphql_client_codegen/src/codegen.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use schema;
99
use selection::Selection;
1010

1111
/// Selects the first operation matching `struct_name` or the first one. Returns `None` when the query document defines no operation.
12-
pub(crate) fn select_operation(query: &query::Document, struct_name: &str) -> Option<Operation> {
12+
pub(crate) fn select_operation<'query>(
13+
query: &'query query::Document,
14+
struct_name: &str,
15+
) -> Option<Operation<'query>> {
1316
let operations = all_operations(query);
1417

1518
operations
@@ -31,9 +34,9 @@ pub(crate) fn all_operations(query: &query::Document) -> Vec<Operation> {
3134
}
3235

3336
/// The main code generation function.
34-
pub fn response_for_query(
35-
schema: schema::Schema,
36-
query: query::Document,
37+
pub(crate) fn response_for_query(
38+
schema: &schema::Schema,
39+
query: &query::Document,
3740
operation: &Operation,
3841
additional_derives: Option<String>,
3942
deprecation_strategy: deprecation::DeprecationStrategy,
@@ -47,17 +50,17 @@ pub fn response_for_query(
4750

4851
let mut definitions = Vec::new();
4952

50-
for definition in query.definitions {
53+
for definition in &query.definitions {
5154
match definition {
5255
query::Definition::Operation(_op) => (),
5356
query::Definition::Fragment(fragment) => {
54-
let query::TypeCondition::On(on) = fragment.type_condition;
57+
let &query::TypeCondition::On(ref on) = &fragment.type_condition;
5558
context.fragments.insert(
56-
fragment.name.clone(),
59+
&fragment.name,
5760
GqlFragment {
58-
name: fragment.name,
61+
name: &fragment.name,
5962
selection: Selection::from(&fragment.selection_set),
60-
on,
63+
on: on,
6164
is_required: false.into(),
6265
},
6366
);
@@ -67,7 +70,7 @@ pub fn response_for_query(
6770

6871
let response_data_fields = {
6972
let opt_root_name = operation.root_name(&context.schema);
70-
let root_name: String = if let Some(root_name) = opt_root_name {
73+
let root_name: &str = if let Some(root_name) = opt_root_name {
7174
root_name
7275
} else {
7376
panic!(

graphql_client_codegen/src/constants.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ use objects::GqlObjectField;
44

55
pub(crate) const TYPENAME_FIELD: &str = "__typename";
66

7-
pub(crate) fn string_type() -> String {
8-
"String".to_string()
7+
pub(crate) fn string_type() -> &'static str {
8+
"String"
99
}
1010

1111
#[cfg(test)]
12-
pub(crate) fn float_type() -> String {
13-
"Float".to_string()
12+
pub(crate) fn float_type() -> &'static str {
13+
"Float"
1414
}
1515

16-
pub(crate) fn typename_field() -> GqlObjectField {
16+
pub(crate) fn typename_field() -> GqlObjectField<'static> {
1717
GqlObjectField {
1818
description: None,
19-
name: TYPENAME_FIELD.to_string(),
19+
name: TYPENAME_FIELD,
2020
/// Non-nullable, see spec:
2121
/// https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md
2222
type_: FieldType::Named(string_type()),

graphql_client_codegen/src/enums.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ use std::cell::Cell;
44
pub const ENUMS_PREFIX: &str = "";
55

66
#[derive(Debug, Clone, PartialEq)]
7-
pub struct EnumVariant {
8-
pub description: Option<String>,
9-
pub name: String,
7+
pub struct EnumVariant<'schema> {
8+
pub description: Option<&'schema str>,
9+
pub name: &'schema str,
1010
}
1111

1212
#[derive(Debug, Clone, PartialEq)]
13-
pub struct GqlEnum {
14-
pub description: Option<String>,
15-
pub name: String,
16-
pub variants: Vec<EnumVariant>,
13+
pub struct GqlEnum<'schema> {
14+
pub description: Option<&'schema str>,
15+
pub name: &'schema str,
16+
pub variants: Vec<EnumVariant<'schema>>,
1717
pub is_required: Cell<bool>,
1818
}
1919

20-
impl GqlEnum {
20+
impl<'schema> GqlEnum<'schema> {
2121
pub(crate) fn to_rust(&self, query_context: &::query::QueryContext) -> TokenStream {
2222
let derives = query_context.response_enum_derives();
2323
let variant_names: Vec<TokenStream> = self
@@ -41,7 +41,7 @@ impl GqlEnum {
4141
})
4242
.collect();
4343
let constructors = &constructors;
44-
let variant_str: Vec<&str> = self.variants.iter().map(|v| v.name.as_str()).collect();
44+
let variant_str: Vec<&str> = self.variants.iter().map(|v| v.name).collect();
4545
let variant_str = &variant_str;
4646

4747
let name = name_ident.clone();

graphql_client_codegen/src/field_type.rs

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ use query::QueryContext;
66
use schema::DEFAULT_SCALARS;
77

88
#[derive(Clone, Debug, PartialEq, Hash)]
9-
pub enum FieldType {
10-
Named(String),
11-
Optional(Box<FieldType>),
12-
Vector(Box<FieldType>),
9+
pub enum FieldType<'a> {
10+
Named(&'a str),
11+
Optional(Box<FieldType<'a>>),
12+
Vector(Box<FieldType<'a>>),
1313
}
1414

15-
impl FieldType {
15+
impl<'a> FieldType<'a> {
1616
/// Takes a field type with its name
1717
pub(crate) fn to_rust(&self, context: &QueryContext, prefix: &str) -> TokenStream {
18-
let prefix: String = if prefix.is_empty() {
19-
self.inner_name_string()
18+
let prefix: &str = if prefix.is_empty() {
19+
self.inner_name_str()
2020
} else {
21-
prefix.to_string()
21+
prefix
2222
};
2323
match &self {
2424
FieldType::Named(ref name) => {
@@ -30,7 +30,7 @@ impl FieldType {
3030
.is_some()
3131
|| DEFAULT_SCALARS.iter().any(|elem| elem == name)
3232
{
33-
name.clone()
33+
name.to_string()
3434
} else if context
3535
.schema
3636
.enums
@@ -43,7 +43,7 @@ impl FieldType {
4343
if prefix.is_empty() {
4444
panic!("Empty prefix for {:?}", self);
4545
}
46-
prefix
46+
prefix.to_string()
4747
};
4848
let full_name = Ident::new(&full_name, Span::call_site());
4949

@@ -61,11 +61,11 @@ impl FieldType {
6161
}
6262

6363
/// Return the innermost name - we mostly use this for looking types up in our Schema struct.
64-
pub fn inner_name_string(&self) -> String {
64+
pub fn inner_name_str(&self) -> &str {
6565
match &self {
66-
FieldType::Named(name) => name.to_string(),
67-
FieldType::Optional(inner) => inner.inner_name_string(),
68-
FieldType::Vector(inner) => inner.inner_name_string(),
66+
FieldType::Named(name) => name,
67+
FieldType::Optional(inner) => inner.inner_name_str(),
68+
FieldType::Vector(inner) => inner.inner_name_str(),
6969
}
7070
}
7171

@@ -77,16 +77,19 @@ impl FieldType {
7777
}
7878
}
7979

80-
impl ::std::convert::From<graphql_parser::schema::Type> for FieldType {
81-
fn from(schema_type: graphql_parser::schema::Type) -> FieldType {
80+
impl<'schema> ::std::convert::From<&'schema graphql_parser::schema::Type> for FieldType<'schema> {
81+
fn from(schema_type: &'schema graphql_parser::schema::Type) -> FieldType<'schema> {
8282
from_schema_type_inner(schema_type, false)
8383
}
8484
}
8585

86-
fn from_schema_type_inner(inner: graphql_parser::schema::Type, non_null: bool) -> FieldType {
86+
fn from_schema_type_inner<'schema>(
87+
inner: &'schema graphql_parser::schema::Type,
88+
non_null: bool,
89+
) -> FieldType<'schema> {
8790
match inner {
8891
graphql_parser::schema::Type::ListType(inner) => {
89-
let inner = from_schema_type_inner(*inner, false);
92+
let inner = from_schema_type_inner(&*inner, false);
9093
let f = FieldType::Vector(Box::new(inner));
9194
if non_null {
9295
f
@@ -102,21 +105,21 @@ fn from_schema_type_inner(inner: graphql_parser::schema::Type, non_null: bool) -
102105
FieldType::Optional(Box::new(f))
103106
}
104107
}
105-
graphql_parser::schema::Type::NonNullType(inner) => from_schema_type_inner(*inner, true),
108+
graphql_parser::schema::Type::NonNullType(inner) => from_schema_type_inner(&*inner, true),
106109
}
107110
}
108111

109112
fn from_json_type_inner(inner: &introspection_response::TypeRef, non_null: bool) -> FieldType {
110113
use introspection_response::*;
111-
let inner = inner.clone();
112114

113115
match inner.kind {
114-
Some(__TypeKind::NON_NULL) => {
115-
from_json_type_inner(&inner.of_type.expect("inner type is missing"), true)
116-
}
116+
Some(__TypeKind::NON_NULL) => from_json_type_inner(
117+
&inner.of_type.as_ref().expect("inner type is missing"),
118+
true,
119+
),
117120
Some(__TypeKind::LIST) => {
118121
let f = FieldType::Vector(Box::new(from_json_type_inner(
119-
&inner.of_type.expect("inner type is missing"),
122+
&inner.of_type.as_ref().expect("inner type is missing"),
120123
false,
121124
)));
122125
if non_null {
@@ -126,7 +129,7 @@ fn from_json_type_inner(inner: &introspection_response::TypeRef, non_null: bool)
126129
}
127130
}
128131
Some(_) => {
129-
let f = FieldType::Named(inner.name.expect("type name").clone());
132+
let f = FieldType::Named(&inner.name.as_ref().expect("type name"));
130133
if non_null {
131134
f
132135
} else {
@@ -137,14 +140,18 @@ fn from_json_type_inner(inner: &introspection_response::TypeRef, non_null: bool)
137140
}
138141
}
139142

140-
impl ::std::convert::From<introspection_response::FullTypeFieldsType> for FieldType {
141-
fn from(schema_type: introspection_response::FullTypeFieldsType) -> FieldType {
143+
impl<'schema> ::std::convert::From<&'schema introspection_response::FullTypeFieldsType>
144+
for FieldType<'schema>
145+
{
146+
fn from(
147+
schema_type: &'schema introspection_response::FullTypeFieldsType,
148+
) -> FieldType<'schema> {
142149
from_json_type_inner(&schema_type.type_ref, false)
143150
}
144151
}
145152

146-
impl ::std::convert::From<introspection_response::InputValueType> for FieldType {
147-
fn from(schema_type: introspection_response::InputValueType) -> FieldType {
153+
impl<'a> ::std::convert::From<&'a introspection_response::InputValueType> for FieldType<'a> {
154+
fn from(schema_type: &'a introspection_response::InputValueType) -> FieldType<'a> {
148155
from_json_type_inner(&schema_type.type_ref, false)
149156
}
150157
}
@@ -157,29 +164,29 @@ mod tests {
157164

158165
#[test]
159166
fn field_type_from_graphql_parser_schema_type_works() {
160-
let ty = GqlParserType::NamedType("Cat".to_string());
167+
let ty = GqlParserType::NamedType("Cat".to_owned());
161168
assert_eq!(
162-
FieldType::from(ty),
163-
FieldType::Optional(Box::new(FieldType::Named("Cat".to_string())))
169+
FieldType::from(&ty),
170+
FieldType::Optional(Box::new(FieldType::Named("Cat")))
164171
);
165172

166-
let ty = GqlParserType::NonNullType(Box::new(GqlParserType::NamedType("Cat".to_string())));
173+
let ty = GqlParserType::NonNullType(Box::new(GqlParserType::NamedType("Cat".to_owned())));
167174

168-
assert_eq!(FieldType::from(ty), FieldType::Named("Cat".to_string()));
175+
assert_eq!(FieldType::from(&ty), FieldType::Named("Cat"));
169176
}
170177

171178
#[test]
172179
fn field_type_from_introspection_response_works() {
173180
let ty = FullTypeFieldsType {
174181
type_ref: TypeRef {
175182
kind: Some(__TypeKind::OBJECT),
176-
name: Some("Cat".to_string()),
183+
name: Some("Cat".into()),
177184
of_type: None,
178185
},
179186
};
180187
assert_eq!(
181-
FieldType::from(ty),
182-
FieldType::Optional(Box::new(FieldType::Named("Cat".to_string())))
188+
FieldType::from(&ty),
189+
FieldType::Optional(Box::new(FieldType::Named("Cat")))
183190
);
184191

185192
let ty = FullTypeFieldsType {
@@ -188,11 +195,11 @@ mod tests {
188195
name: None,
189196
of_type: Some(Box::new(TypeRef {
190197
kind: Some(__TypeKind::OBJECT),
191-
name: Some("Cat".to_string()),
198+
name: Some("Cat".into()),
192199
of_type: None,
193200
})),
194201
},
195202
};
196-
assert_eq!(FieldType::from(ty), FieldType::Named("Cat".to_string()));
203+
assert_eq!(FieldType::from(&ty), FieldType::Named("Cat"));
197204
}
198205
}

graphql_client_codegen/src/fragments.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ use std::cell::Cell;
55

66
/// Represents a fragment extracted from a query document.
77
#[derive(Debug, PartialEq)]
8-
pub(crate) struct GqlFragment {
8+
pub(crate) struct GqlFragment<'query> {
99
/// The name of the fragment, matching one-to-one with the name in the GraphQL query document.
10-
pub name: String,
10+
pub name: &'query str,
1111
/// The `on` clause of the fragment.
12-
pub on: String,
12+
pub on: &'query str,
1313
/// The selected fields.
14-
pub selection: Selection,
15-
/// Whether the fragment
14+
pub selection: Selection<'query>,
15+
/// Whether the fragment is used in the current query
1616
pub is_required: Cell<bool>,
1717
}
1818

19-
impl GqlFragment {
19+
impl<'query> GqlFragment<'query> {
2020
/// Generate all the Rust code required by the fragment's selection.
2121
pub(crate) fn to_rust(&self, context: &QueryContext) -> Result<TokenStream, ::failure::Error> {
2222
if let Some(obj) = context.schema.objects.get(&self.on) {

0 commit comments

Comments
 (0)