{{
    const spec = require('./.spec.json');
    const dotUtils = require('./dotUtils.js');
}}{{= dotUtils.preamble() }}

// http://www.mingweisamuel.com/riotapi-schema/tool/
// Version {{= spec.info.version }}

#![allow(missing_docs)]

//! Data transfer structs.
//!
//! Separated into separate modules for each endpoint.
//! Several modules contain structs with the same name, so be sure to use the right ones.
//!
//! Note: these modules are automatically generated.

{{
    let schemas = spec.components.schemas;
    let schemaKeyByEndpoint = Object.keys(schemas)
        .filter(schemaKey => 'Error' != schemaKey)
        .groupBy(schemaKey => schemaKey.split('.')[0]);

    for (let [endpoint, schemaKeyGroup] of schemaKeyByEndpoint) {
        const endpoint_pascal_case = dotUtils.changeCase.pascalCase(endpoint);
}}
/// Data structs used by [`{{= endpoint_pascal_case }}`](crate::endpoints::{{= endpoint_pascal_case }}).
/// 
/// Note: this module is automatically generated.
#[allow(dead_code)]
pub mod {{= dotUtils.changeCase.snakeCase(endpoint) }} {
{{
        for (let schemaKey of schemaKeyGroup) {
            const [, rawSchemaName] = schemaKey.split('.');
            const schemaName = dotUtils.normalizeSchemaName(rawSchemaName);
            const schema = schemas[schemaKey];
            const props = schema.properties;
            const requiredSet = new Set(schema.required);
}}
    /// {{= schemaName }} data object.
{{? schema.description }}
    /// # Description
    /// {{= schema.description.split('\n').map(x => x.trim()).join('<br>\r\n    /// ') }}
    ///
    /// Note: This struct is automatically generated
{{?}}
    #[derive(Clone, Debug)]
    #[derive(serde::Serialize, serde::Deserialize)]
    #[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
    pub struct {{= schemaName }} {
{{
            const usedNames = new Set();
            for (let [ propKey, prop ] of Object.entries(props))
            {
                const optional = !requiredSet.has(propKey);

                let name = dotUtils.normalizePropName(propKey);
                while (usedNames.has(name)) {
                    name += '_';
                }
                usedNames.add(name);
}}
{{? prop.description }}
        /// {{= prop.description.split('\n').map(x => x.trim()).join('<br>\r\n        /// ') }}
{{?}}
        {{= dotUtils.formatJsonProperty(propKey, prop) }}
{{? optional }}
        #[serde(skip_serializing_if = "Option::is_none")]
{{?}}
{{? 'championId' === propKey && (prop.description || '').includes('this field returned invalid championIds') }}
        ///
        /// Instead use [`Self::champion()`] which checks this field then parses [`Self::champion_name`].
        #[deprecated(since = "2.5.0", note = "Use `Participant.champion()` instead. Riot sometimes returns corrupted data for this field: https://github.com/RiotGames/developer-relations/issues/553")]
        #[serde(serialize_with = "crate::consts::Champion::serialize_result")]
        #[serde(deserialize_with = "crate::consts::Champion::deserialize_result")]
        pub {{= name }}: Result<crate::consts::Champion, std::num::TryFromIntError>,
{{?? 'gameType' === propKey && 'Info' === schemaName && 'match-v5' === endpoint }}
        ///
        /// Will be `None` if empty string is returned: https://github.com/RiotGames/developer-relations/issues/898
        #[serde(serialize_with = "crate::consts::serialize_empty_string_none")]
        #[serde(deserialize_with = "crate::consts::deserialize_empty_string_none")]
        pub {{= name }}: Option<crate::consts::GameType>,
{{??}}
        pub {{= name }}: {{= dotUtils.stringifyType(prop, { optional }) }},
{{?}}
{{
            }
}}
    }
{{
        }
}}
}

{{
    }
}}