tdlib_tl_gen/
functions.rs

1// Copyright 2020 - developers of the `grammers` project.
2// Copyright 2021 - developers of the `tdlib-rs` project.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! Code to generate Rust's `fn`'s from TL definitions.
11
12use crate::metadata::Metadata;
13use crate::rustifier;
14use std::io::{self, Write};
15use tdlib_tl_parser::tl::{Category, Definition};
16
17/// Defines the `function` corresponding to the definition:
18///
19/// ```ignore
20/// pub async fn name(client_id: i32, field: Type) -> Result {
21///
22/// }
23/// ```
24fn write_function<W: Write>(
25    file: &mut W,
26    def: &Definition,
27    _metadata: &Metadata,
28    gen_bots_only_api: bool,
29) -> io::Result<()> {
30    if rustifier::definitions::is_for_bots_only(def) && !gen_bots_only_api {
31        return Ok(());
32    }
33
34    // Documentation
35    writeln!(file, "{}", rustifier::definitions::description(def, "    "))?;
36    writeln!(file, "    /// # Arguments")?;
37    for param in def.params.iter() {
38        if rustifier::parameters::is_for_bots_only(param) && !gen_bots_only_api {
39            continue;
40        }
41
42        writeln!(
43            file,
44            "    /// * `{}` - {}",
45            rustifier::parameters::attr_name(param),
46            param.description.replace('\n', "\n    /// ")
47        )?;
48    }
49    writeln!(
50        file,
51        "    /// * `client_id` - The client id to send the request to"
52    )?;
53
54    // Function
55    writeln!(file, "    #[allow(clippy::too_many_arguments)]")?;
56    write!(
57        file,
58        "    pub async fn {}(",
59        rustifier::definitions::function_name(def)
60    )?;
61    for param in def.params.iter() {
62        if rustifier::parameters::is_for_bots_only(param) && !gen_bots_only_api {
63            continue;
64        }
65
66        write!(file, "{}: ", rustifier::parameters::attr_name(param))?;
67
68        let is_optional = rustifier::parameters::is_optional(param);
69        if is_optional {
70            write!(file, "Option<")?;
71        }
72        write!(file, "{}", rustifier::parameters::qual_name(param))?;
73        if is_optional {
74            write!(file, ">")?;
75        }
76
77        write!(file, ", ")?;
78    }
79
80    writeln!(
81        file,
82        "client_id: i32) -> Result<{}, crate::types::Error> {{",
83        rustifier::types::qual_name(&def.ty, false)
84    )?;
85
86    // Compose request
87    writeln!(file, "        let request = json!({{")?;
88    writeln!(file, "            \"@type\": \"{}\",", def.name)?;
89    for param in def.params.iter() {
90        if rustifier::parameters::is_for_bots_only(param) && !gen_bots_only_api {
91            continue;
92        }
93
94        writeln!(
95            file,
96            "            \"{0}\": {1},",
97            param.name,
98            rustifier::parameters::attr_name(param),
99        )?;
100    }
101    writeln!(file, "        }});")?;
102
103    // Send request
104    writeln!(
105        file,
106        "        let response = send_request(client_id, request).await;"
107    )?;
108    writeln!(file, "        if response[\"@type\"] == \"error\" {{")?;
109    writeln!(
110        file,
111        "            return Err(serde_json::from_value(response).unwrap())"
112    )?;
113    writeln!(file, "        }}")?;
114
115    if rustifier::types::is_ok(&def.ty) {
116        writeln!(file, "        Ok(())")?;
117    } else {
118        writeln!(
119            file,
120            "        Ok(serde_json::from_value(response).unwrap())"
121        )?;
122    }
123
124    writeln!(file, "    }}")?;
125    Ok(())
126}
127
128/// Writes an entire definition as Rust code (`fn`).
129fn write_definition<W: Write>(
130    file: &mut W,
131    def: &Definition,
132    metadata: &Metadata,
133    gen_bots_only_api: bool,
134) -> io::Result<()> {
135    write_function(file, def, metadata, gen_bots_only_api)?;
136    Ok(())
137}
138
139/// Write the entire module dedicated to functions.
140pub(crate) fn write_functions_mod<W: Write>(
141    mut file: &mut W,
142    definitions: &[Definition],
143    metadata: &Metadata,
144    gen_bots_only_api: bool,
145) -> io::Result<()> {
146    // Begin outermost mod
147    writeln!(file, "pub mod functions {{")?;
148    writeln!(file, "    use serde_json::json;")?;
149    writeln!(file, "    use crate::send_request;")?;
150
151    let functions = definitions
152        .iter()
153        .filter(|d| d.category == Category::Functions);
154
155    for definition in functions {
156        write_definition(&mut file, definition, metadata, gen_bots_only_api)?;
157    }
158
159    // End outermost mod
160    writeln!(file, "}}")
161}