//! # A GraphQL server library implemented in Rust
//!
//! <div align="center">
//! <!-- CI -->
//! <img src="https://github.com/async-graphql/async-graphql/workflows/CI/badge.svg" />
//! <!-- codecov -->
//! <img src="https://codecov.io/gh/async-graphql/async-graphql/branch/master/graph/badge.svg" />
//! <!-- Crates version -->
//! <a href="https://crates.io/crates/async-graphql">
//! <img src="https://img.shields.io/crates/v/async-graphql.svg?style=flat-square"
//! alt="Crates.io version" />
//! </a>
//! <!-- Downloads -->
//! <a href="https://crates.io/crates/async-graphql">
//! <img src="https://img.shields.io/crates/d/async-graphql.svg?style=flat-square"
//! alt="Download" />
//! </a>
//! <!-- docs.rs docs -->
//! <a href="https://docs.rs/async-graphql">
//! <img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square"
//! alt="docs.rs docs" />
//! </a>
//! <a href="https://github.com/rust-secure-code/safety-dance/">
//! <img src="https://img.shields.io/badge/unsafe-forbidden-success.svg?style=flat-square"
//! alt="Unsafe Rust forbidden" />
//! </a>
//! </div>
//!
//! ## Documentation
//!
//! * [Feature Comparison](feature-comparison.md)
//! * [Book](https://async-graphql.github.io/async-graphql/en/index.html)
//! * [中文文档](https://async-graphql.github.io/async-graphql/zh-CN/index.html)
//! * [Docs](https://docs.rs/async-graphql)
//! * [GitHub repository](https://github.com/async-graphql/async-graphql)
//! * [Cargo package](https://crates.io/crates/async-graphql)
//! * Minimum supported Rust version: 1.42 or later
//!
//! ## Features
//!
//! * Fully supports async/await
//! * Type safety
//! * Rustfmt friendly (Procedural Macro)
//! * Custom scalars
//! * Minimal overhead
//! * Easy integration (actix_web, tide, warp, rocket ...)
//! * File upload (Multipart request)
//! * Subscriptions (WebSocket transport)
//! * Custom extensions
//! * Apollo Tracing extension
//! * Limit query complexity/depth
//! * Error Extensions
//! * Apollo Federation
//! * Batch Queries
//! * Apollo Persisted Queries
//!
//! # Crate features
//!
//! This crate offers the following features, all of which are activated by default:
//!
//! **I recommend that you always turn off all features and turn them on only
//! when needed, which can significantly increase compilation speed.**
//!
//! ```toml
//! async-graphql = { version = "*", default-features = false }
//! ```
//!
//! - `apollo_tracing`: Enable the [Apollo tracing extension](extensions/struct.ApolloTracing.html).
//! - `apollo_persisted_queries`: Enable the [Apollo persisted queries extension](extensions/apollo_persisted_queries/struct.ApolloPersistedQueries.html).
//! - `log`: Enable the [logger extension](extensions/struct.Logger.html).
//! - `tracing`: Enable the [tracing extension](extensions/struct.Tracing.html).
//! - `multipart`: Support [sending files over HTTP multipart](http/fn.receive_body.html).
//! - `unblock`: Support [asynchronous reader for Upload](types/struct.Upload.html)
//! - `bson`: Integrate with the [`bson` crate](https://crates.io/crates/bson).
//! - `chrono`: Integrate with the [`chrono` crate](https://crates.io/crates/chrono).
//! - `chrono-tz`: Integrate with the [`chrono-tz` crate](https://crates.io/crates/chrono-tz).
//! - `url`: Integrate with the [`url` crate](https://crates.io/crates/url).
//! - `uuid`: Integrate with the [`uuid` crate](https://crates.io/crates/uuid).
//! - `string_number`: Enable the [StringNumber](types/struct.StringNumber.html).
//!
//! ## Integrations
//!
//! * Actix-web [async-graphql-actix_web](https://crates.io/crates/async-graphql-actix-web)
//! * Warp [async-graphql-warp](https://crates.io/crates/async-graphql-warp)
//! * Tide [async-graphql-tide](https://crates.io/crates/async-graphql-tide)
//!
//! ## License
//!
//! Licensed under either of
//!
//! * Apache License, Version 2.0,
//! (./LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
//! * MIT license (./LICENSE-MIT or <http://opensource.org/licenses/MIT>)
//! at your option.
//!
//! ## References
//!
//! * [GraphQL](https://graphql.org)
//! * [GraphQL Multipart Request](https://github.com/jaydenseric/graphql-multipart-request-spec)
//! * [GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)
//! * [GraphQL over WebSocket Protocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md)
//! * [Apollo Tracing](https://github.com/apollographql/apollo-tracing)
//! * [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction)
//!
//! ## Examples
//!
//! All examples are in the [sub-repository](https://github.com/async-graphql/examples), located in the examples directory.
//!
//! **Run an example:**
//!
//! ```shell
//! git submodule update # update the examples repo
//! cd examples && cargo run --bin [name]
//! ```
//!
//! ## Benchmarks
//!
//! Ensure that there is no CPU-heavy process in background!
//!
//! ```shell script
//! cd benchmark
//! cargo bench
//! ```
//!
//! Now a HTML report is available at `benchmark/target/criterion/report`.
//!

#![deny(clippy::all)]
// #![deny(clippy::pedantic)]
#![deny(clippy::inefficient_to_string)]
#![deny(clippy::match_wildcard_for_single_variants)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::similar_names)]
#![allow(clippy::if_not_else)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::needless_pass_by_value)]
#![deny(clippy::redundant_closure_for_method_calls)]
#![allow(clippy::option_if_let_else)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::filter_map)]
#![allow(clippy::default_trait_access)]
#![allow(clippy::map_flatten)]
#![allow(clippy::map_unwrap_or)]
#![allow(clippy::explicit_iter_loop)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::unused_self)]
#![allow(clippy::find_map)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::implicit_hasher)]
// #![deny(clippy::nursery)]
#![allow(clippy::use_self)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::needless_borrow)]
#![allow(clippy::future_not_send)]
#![allow(clippy::redundant_pub_crate)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::useless_let_if_seq)]
#![warn(missing_docs)]
#![allow(clippy::trivially_copy_pass_by_ref)]
#![recursion_limit = "256"]
#![forbid(unsafe_code)]
#![cfg_attr(feature = "nightly", feature(doc_cfg))]

mod base;
mod error;
mod look_ahead;
mod model;
mod request;
mod response;
mod schema;
mod subscription;
mod validation;

pub mod context;
pub mod extensions;
pub mod guard;
pub mod http;
pub mod resolver_utils;
pub mod types;
pub mod validators;

#[doc(hidden)]
pub mod registry;

#[doc(hidden)]
pub use async_stream;
#[doc(hidden)]
pub use async_trait;
#[doc(hidden)]
pub use context::ContextSelectionSet;
#[doc(hidden)]
pub use futures_util;
#[doc(hidden)]
pub use indexmap;
#[doc(hidden)]
pub use static_assertions;
#[doc(hidden)]
pub use subscription::SubscriptionType;

pub use async_graphql_parser as parser;
pub use async_graphql_value::{
    from_value, to_value, value, ConstValue as Value, DeserializerError, Name, Number,
    SerializerError,
};
pub use base::{
    Description, InputObjectType, InputType, InterfaceType, ObjectType, OutputType, Type, UnionType,
};
pub use error::{
    Error, ErrorExtensionValues, ErrorExtensions, InputValueError, InputValueResult,
    ParseRequestError, PathSegment, Result, ResultExt, ServerError, ServerResult,
};
pub use look_ahead::Lookahead;
pub use registry::CacheControl;
pub use request::{BatchRequest, Request};
#[doc(no_inline)]
pub use resolver_utils::{ContainerType, EnumType, ScalarType};
pub use response::{BatchResponse, Response};
pub use schema::{Schema, SchemaBuilder, SchemaEnv};
pub use validation::{ValidationMode, ValidationResult, VisitorContext};

pub use context::*;
#[doc(no_inline)]
pub use parser::{Pos, Positioned};
pub use types::*;

/// An alias of [async_graphql::Error](struct.Error.html). Present for backward compatibility
/// reasons.
pub type FieldError = Error;

/// An alias of [async_graphql::Result](type.Result.html). Present for backward compatibility
/// reasons.
pub type FieldResult<T> = Result<T>;

/// Define a GraphQL object with methods
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_complex_object.html).*
///
/// All methods are converted to camelCase.
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | rename_args   | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | cache_control | Object cache control      | [`CacheControl`](struct.CacheControl.html) | Y        |
/// | extends       | Add fields to an entity that's defined in another service | bool | Y |
/// | use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | Y |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | skip          | Skip this field           | bool     | Y        |
/// | name          | Field name                | string   | Y        |
/// | desc          | Field description         | string   | Y        |
/// | deprecation   | Field deprecation reason  | string   | Y        |
/// | cache_control | Field cache control       | [`CacheControl`](struct.CacheControl.html) | Y        |
/// | external      | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
/// | provides      | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
/// | requires      | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
/// | guard         | Field of guard            | [`Guard`](guard/trait.Guard.html) | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field argument parameters
///
/// | Attribute    | description                              | Type        | Optional |
/// |--------------|------------------------------------------|------------ |----------|
/// | name         | Argument name                            | string      | Y        |
/// | desc         | Argument description                     | string      | Y        |
/// | default      | Use `Default::default` for default value | none        | Y        |
/// | default      | Argument default value                   | literal     | Y        |
/// | default_with | Expression to generate default value     | code string | Y        |
/// | validator    | Input value validator                    | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y        |
/// | complexity   | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).*                 | bool        | Y        |
/// | complexity   | Custom field complexity.                 | string      | Y        |
/// | visible      | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible      | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
/// | key          | Is entity key(for Federation)            | bool        | Y        |
///
/// # Valid field return types
///
/// - Scalar values, such as `i32` and `bool`. `usize`, `isize`, `u128` and `i128` are not
/// supported
/// - `Vec<T>`, such as `Vec<i32>`
/// - Slices, such as `&[i32]`
/// - `Option<T>`, such as `Option<i32>`
/// - `BTree<T>`, `HashMap<T>`, `HashSet<T>`, `BTreeSet<T>`, `LinkedList<T>`, `VecDeque<T>`
/// - GraphQL objects.
/// - GraphQL enums.
/// - References to any of the above types, such as `&i32` or `&Option<String>`.
/// - `Result<T, E>`, such as `Result<i32, E>`
///
/// # Context
///
/// You can define a context as an argument to a method, and the context should be the first argument to the method.
///
/// ```ignore
/// #[Object]
/// impl QueryRoot {
///     async fn value(&self, ctx: &Context<'_>) -> { ... }
/// }
/// ```
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// struct QueryRoot {
///     value: i32,
/// }
///
/// #[Object]
/// impl QueryRoot {
///     /// value
///     async fn value(&self) -> i32 {
///         self.value
///     }
///
///     /// reference value
///     async fn value_ref(&self) -> &i32 {
///         &self.value
///     }
///
///     /// value with error
///     async fn value_with_error(&self) -> Result<i32> {
///         Ok(self.value)
///     }
///
///     async fn value_with_arg(&self, #[graphql(default = 1)] a: i32) -> i32 {
///         a
///     }
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::new(QueryRoot { value: 10 }, EmptyMutation, EmptySubscription);
///     let res = schema.execute(r#"{
///         value
///         valueRef
///         valueWithError
///         valueWithArg1: valueWithArg
///         valueWithArg2: valueWithArg(a: 99)
///     }"#).await.into_result().unwrap().data;
///     assert_eq!(res, value!({
///         "value": 10,
///         "valueRef": 10,
///         "valueWithError": 10,
///         "valueWithArg1": 1,
///         "valueWithArg2": 99
///     }));
/// });
/// ```
pub use async_graphql_derive::Object;

/// Define a GraphQL object with fields
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_simple_object.html).*
///
/// Similar to `Object`, but defined on a structure that automatically generates getters for all fields. For a list of valid field types, see [`Object`](attr.Object.html). All fields are converted to camelCase.
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | cache_control | Object cache control      | [`CacheControl`](struct.CacheControl.html) | Y        |
/// | extends       | Add fields to an entity that's defined in another service | bool | Y |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | skip          | Skip this field           | bool     | Y        |
/// | name          | Field name                | string   | Y        |
/// | deprecation   | Field deprecation reason  | string   | Y        |
/// | owned         | Field resolver return a ownedship value  | bool   | Y        |
/// | cache_control | Field cache control       | [`CacheControl`](struct.CacheControl.html) | Y        |
/// | external      | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
/// | provides      | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
/// | requires      | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
/// | guard         | Field of guard            | [`Guard`](guard/trait.Guard.html) | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// #[derive(SimpleObject)]
/// struct QueryRoot {
///     value: i32,
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::new(QueryRoot{ value: 10 }, EmptyMutation, EmptySubscription);
///     let res = schema.execute("{ value }").await.into_result().unwrap().data;
///     assert_eq!(res, value!({
///         "value": 10,
///     }));
/// });
/// ```
pub use async_graphql_derive::SimpleObject;

/// Define a GraphQL enum
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_enum.html).*
///
/// # Macro parameters
///
/// | Attribute    | description               | Type     | Optional |
/// |--------------|---------------------------|----------|----------|
/// | name         | Enum name                 | string   | Y        |
/// | rename_items | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | remote       | Derive a remote enum      | string   | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Item parameters
///
/// | Attribute   | description               | Type     | Optional |
/// |-------------|---------------------------|----------|----------|
/// | name        | Item name                 | string   | Y        |
/// | deprecation | Item deprecation reason   | string   | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// #[derive(Enum, Copy, Clone, Eq, PartialEq)]
/// enum MyEnum {
///     A,
///     #[graphql(name = "b")] B,
/// }
///
/// struct QueryRoot {
///     value1: MyEnum,
///     value2: MyEnum,
/// }
///
/// #[Object]
/// impl QueryRoot {
///     /// value1
///     async fn value1(&self) -> MyEnum {
///         self.value1
///     }
///
///     /// value2
///     async fn value2(&self) -> MyEnum {
///         self.value2
///     }
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::new(QueryRoot{ value1: MyEnum::A, value2: MyEnum::B }, EmptyMutation, EmptySubscription);
///     let res = schema.execute("{ value1 value2 }").await.into_result().unwrap().data;
///     assert_eq!(res, value!({ "value1": "A", "value2": "b" }));
/// });
/// ```
pub use async_graphql_derive::Enum;

/// Define a GraphQL input object
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_input_object.html).*
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field parameters
///
/// | Attribute    | description                              | Type        | Optional |
/// |--------------|------------------------------------------|-------------|----------|
/// | name         | Field name                               | string      | Y        |
/// | default      | Use `Default::default` for default value | none        | Y        |
/// | default      | Argument default value                   | literal     | Y        |
/// | default_with | Expression to generate default value     | code string | Y        |
/// | validator    | Input value validator                    | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y        |
/// | flatten      | Similar to serde (flatten)               | boolean     | Y        |
/// | skip         | Skip this field, use `Default::default` to get a default value for this field. | bool     | Y        |
/// | visible      | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible      | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// #[derive(InputObject)]
/// struct MyInputObject {
///     a: i32,
///     #[graphql(default = 10)]
///     b: i32,
/// }
///
/// struct QueryRoot;
///
/// #[Object]
/// impl QueryRoot {
///     /// value
///     async fn value(&self, input: MyInputObject) -> i32 {
///         input.a * input.b
///     }
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
///     let res = schema.execute(r#"
///     {
///         value1: value(input:{a:9, b:3})
///         value2: value(input:{a:9})
///     }"#).await.into_result().unwrap().data;
///     assert_eq!(res, value!({ "value1": 27, "value2": 90 }));
/// });
/// ```
pub use async_graphql_derive::InputObject;

/// Define a GraphQL interface
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_interface.html).*
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | rename_args   | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | field         | Fields of this Interface  | [InterfaceField] | N |
/// | extends       | Add fields to an entity that's defined in another service | bool | Y |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field parameters
///
/// | Attribute   | description               | Type     | Optional |
/// |-------------|---------------------------|----------|----------|
/// | name        | Field name                | string   | N        |
/// | type        | Field type                | string   | N        |
/// | method      | Rust resolver method name. If specified, `name` will not be camelCased in schema definition | string | Y |
/// | desc        | Field description         | string   | Y        |
/// | deprecation | Field deprecation reason  | string   | Y        |
/// | arg         | Field arguments           | [InterfaceFieldArgument]          | Y        |
/// | external    | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
/// | provides    | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
/// | requires    | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field argument parameters
///
/// | Attribute    | description                              | Type        | Optional |
/// |--------------|------------------------------------------|-------------|----------|
/// | name         | Argument name                            | string      | N        |
/// | type         | Argument type                            | string      | N        |
/// | desc         | Argument description                     | string      | Y        |
/// | default      | Use `Default::default` for default value | none        | Y        |
/// | default      | Argument default value                   | literal     | Y        |
/// | default_with | Expression to generate default value     | code string | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Define an interface
///
/// Define TypeA, TypeB, TypeC... Implement the MyInterface
///
/// ```ignore
/// #[derive(Interface)]
/// enum MyInterface {
///     TypeA(TypeA),
///     TypeB(TypeB),
///     TypeC(TypeC),
///     ...
/// }
/// ```
///
/// # Fields
///
/// The type, name, and parameter fields of the interface must exactly match the type of the
/// implementation interface, but Result can be omitted.
///
/// ```rust
/// use async_graphql::*;
///
/// struct TypeA {
///     value: i32,
/// }
///
/// #[Object]
/// impl TypeA {
///     /// Returns data borrowed from the context
///     async fn value_a<'a>(&self, ctx: &'a Context<'_>) -> Result<&'a str> {
///         Ok(ctx.data::<String>()?.as_str())
///     }
///
///     /// Returns data borrowed self
///     async fn value_b(&self) -> &i32 {
///         &self.value
///     }
///
///     /// With parameters
///     async fn value_c(&self, a: i32, b: i32) -> i32 {
///         a + b
///     }
///
///     /// Disabled name transformation, don't forget "method" argument in interface!
///     #[graphql(name = "value_d")]
///     async fn value_d(&self) -> i32 {
///         &self.value + 1
///     }
/// }
///
/// #[derive(Interface)]
/// #[graphql(
///     field(name = "value_a", type = "&'ctx str"),
///     field(name = "value_b", type = "&i32"),
///     field(name = "value_c", type = "i32",
///         arg(name = "a", type = "i32"),
///         arg(name = "b", type = "i32")),
///     field(name = "value_d", method = "value_d", type = "i32"),
/// )]
/// enum MyInterface {
///     TypeA(TypeA)
/// }
///
/// struct QueryRoot;
///
/// #[Object]
/// impl QueryRoot {
///     async fn type_a(&self) -> MyInterface {
///         TypeA { value: 10 }.into()
///     }
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).data("hello".to_string()).finish();
///     let res = schema.execute(r#"
///     {
///         typeA {
///             valueA
///             valueB
///             valueC(a: 3, b: 2)
///             value_d
///         }
///     }"#).await.into_result().unwrap().data;
///     assert_eq!(res, value!({
///         "typeA": {
///             "valueA": "hello",
///             "valueB": 10,
///             "valueC": 5,
///             "value_d": 11
///         }
///     }));
/// });
/// ```
pub use async_graphql_derive::Interface;

/// Define a GraphQL union
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_union.html).*
///
/// # Macro parameters
///
/// | Attribute   | description               | Type     | Optional |
/// |-------------|---------------------------|----------|----------|
/// | name        | Object name               | string   | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Item parameters
///
/// | Attribute    | description                              | Type     | Optional |
/// |--------------|------------------------------------------|----------|----------|
/// | flatten      | Similar to serde (flatten)               | boolean  | Y        |
///
/// # Define a union
///
/// Define TypeA, TypeB, ... as MyUnion
///
/// ```rust
/// use async_graphql::*;
///
/// #[derive(SimpleObject)]
/// struct TypeA {
///     value_a: i32,
/// }
///
/// #[derive(SimpleObject)]
/// struct TypeB {
///     value_b: i32
/// }
///
/// #[derive(Union)]
/// enum MyUnion {
///     TypeA(TypeA),
///     TypeB(TypeB),
/// }
///
/// struct QueryRoot;
///
/// #[Object]
/// impl QueryRoot {
///     async fn all_data(&self) -> Vec<MyUnion> {
///         vec![TypeA { value_a: 10 }.into(), TypeB { value_b: 20 }.into()]
///     }
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).data("hello".to_string()).finish();
///     let res = schema.execute(r#"
///     {
///         allData {
///             ... on TypeA {
///                 valueA
///             }
///             ... on TypeB {
///                 valueB
///             }
///         }
///     }"#).await.into_result().unwrap().data;
///     assert_eq!(res, value!({
///         "allData": [
///             { "valueA": 10 },
///             { "valueB": 20 },
///         ]
///     }));
/// });
/// ```
pub use async_graphql_derive::Union;

/// Define a GraphQL subscription
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/subscription.html).*
///
/// The field function is a synchronization function that performs filtering. When true is returned, the message is pushed to the client.
/// The second parameter is the type of the field.
/// Starting with the third parameter is one or more filtering conditions, The filter condition is the parameter of the field.
/// The filter function should be synchronous.
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | rename_args   | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string   | Y        |
/// | use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | Y |
///
/// # Field parameters
///
/// | Attribute   | description               | Type     | Optional |
/// |-------------|---------------------------|----------|----------|
/// | name        | Field name                | string   | Y        |
/// | deprecation | Field deprecation reason  | string   | Y        |
/// | guard       | Field of guard            | [`Guard`](guard/trait.Guard.html) | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Field argument parameters
///
/// | Attribute    | description                              | Type        | Optional |
/// |--------------|------------------------------------------|------------ |----------|
/// | name         | Argument name                            | string      | Y        |
/// | desc         | Argument description                     | string      | Y        |
/// | default      | Use `Default::default` for default value | none        | Y        |
/// | default      | Argument default value                   | literal     | Y        |
/// | default_with | Expression to generate default value     | code string | Y        |
/// | validator    | Input value validator                    | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y        |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
/// use futures_util::stream::{Stream, StreamExt};
///
/// struct SubscriptionRoot;
///
/// #[Subscription]
/// impl SubscriptionRoot {
///     async fn value(&self, condition: i32) -> impl Stream<Item = i32> {
///         // Returns the number from 0 to `condition`.
///         futures_util::stream::iter(0..condition)
///     }
/// }
/// ```
pub use async_graphql_derive::Subscription;

/// Define a Scalar
///
/// # Macro parameters
///
/// | Attribute   | description               | Type     | Optional |
/// |-------------|---------------------------|----------|----------|
/// | name        | Scalar name               | string   | Y        |
///
pub use async_graphql_derive::Scalar;

/// Define a merged object with multiple object types.
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/merging_objects.html).*
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
/// | cache_control | Object cache control      | [`CacheControl`](struct.CacheControl.html) | Y        |
/// | extends       | Add fields to an entity that's defined in another service | bool | Y |
/// | use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | Y |
/// | visible       | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible       | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// #[derive(SimpleObject)]
///  struct Object1 {
///     a: i32,
///  }
///
/// #[derive(SimpleObject)]
/// struct Object2 {
///     b: i32,
/// }
///
/// #[derive(SimpleObject)]
/// struct Object3 {
///     c: i32,
/// }
///
/// #[derive(MergedObject)]
/// struct MyObj(Object1, Object2, Object3);
///
/// let obj = MyObj(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 });
/// ```
pub use async_graphql_derive::MergedObject;

/// Define a merged subscription with multiple subscription types.
///
/// *[See also the Book](https://async-graphql.github.io/async-graphql/en/merging_objects.html).*
///
/// # Macro parameters
///
/// | Attribute     | description               | Type     | Optional |
/// |---------------|---------------------------|----------|----------|
/// | name          | Object name               | string   | Y        |
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
/// use futures_util::stream::Stream;
///
/// #[derive(Default)]
/// struct Subscription1;
///
/// #[Subscription]
/// impl Subscription1 {
///     async fn events1(&self) -> impl Stream<Item = i32> {
///         futures_util::stream::iter(0..10)
///     }
/// }
///
/// #[derive(Default)]
/// struct Subscription2;
///
/// #[Subscription]
/// impl Subscription2 {
///     async fn events2(&self) -> impl Stream<Item = i32> {
///         futures_util::stream::iter(10..20)
///    }
/// }
///
/// #[derive(MergedSubscription, Default)]
/// struct Subscription(Subscription1, Subscription2);
/// ```
pub use async_graphql_derive::MergedSubscription;

/// Attach a description to `Object`, `Scalar` or `Subscription`.
///
/// The three types above use the rustdoc on the implementation block as
/// the GraphQL type description, but if you want to use the rustdoc on the
/// type declaration as the GraphQL type description, you can use that derived macro.
///
/// # Examples
///
/// ```rust
/// use async_graphql::*;
///
/// /// This is MyObj
/// #[derive(Description, Default)]
/// struct MyObj;
///
/// #[Object(use_type_description)]
/// impl MyObj {
///     async fn value(&self) -> i32 {
///         100
///     }
/// }
///
/// #[derive(SimpleObject, Default)]
/// struct Query {
///     obj: MyObj,
/// }
///
/// async_std::task::block_on(async move {
///     let schema = Schema::new(Query::default(), EmptyMutation, EmptySubscription);
///     assert_eq!(
///         schema
///             .execute(r#"{ __type(name: "MyObj") { description } }"#)
///             .await
///             .data,
///         value!({
///             "__type": { "description": "This is MyObj" }
///         })
///     );
/// });
/// ```
pub use async_graphql_derive::Description;
