mir/
function.rs

1use crate::{Doc, Ident, Visibility};
2use std::fmt::{Debug, Formatter};
3
4pub enum Arg<T> {
5    /// fn foo(a: i32)
6    Basic {
7        name: Ident,
8        ty: T,
9        default: Option<T>,
10    },
11    /// For typescript
12    /// function foo({foo, bar}: FooProps)
13    Unpack { names: Vec<Ident>, ty: T },
14    /// rust: fn foo(&self)
15    SelfArg { mutable: bool, reference: bool },
16    /// python: def foo(**kwargs)
17    Kwargs { name: Ident, ty: T },
18    /// python: def foo(*args)
19    Variadic { name: Ident, ty: T },
20}
21
22impl<T> Arg<T> {
23    pub fn ident(&self) -> Option<&Ident> {
24        let name = match self {
25            Arg::Basic { name, .. } => name,
26            Arg::Unpack { .. } => return None,
27            Arg::SelfArg { .. } => return None,
28            Arg::Kwargs { name, .. } => name,
29            Arg::Variadic { name, .. } => name,
30        };
31        Some(name)
32    }
33
34    pub fn ty(&self) -> Option<&T> {
35        let ty = match self {
36            Arg::Basic { ty, .. } => ty,
37            Arg::Unpack { ty, .. } => ty,
38            Arg::SelfArg { .. } => return None,
39            Arg::Kwargs { ty, .. } => ty,
40            Arg::Variadic { ty, .. } => ty,
41        };
42        Some(ty)
43    }
44}
45
46pub struct Function<T> {
47    pub name: Ident,
48    pub args: Vec<Arg<T>>,
49    pub ret: T,
50    pub body: T,
51    pub doc: Option<Doc>,
52    pub is_async: bool,
53    pub vis: Visibility,
54    pub attributes: Vec<T>,
55}
56
57impl<T> Function<T> {
58    pub fn body(mut self, body: T) -> Self {
59        self.body = body;
60        self
61    }
62}
63
64impl<T> Debug for Function<T>
65where
66    T: Debug,
67{
68    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
69        f.debug_struct("Function")
70            .field("name", &self.name)
71            .field("ret", &self.ret)
72            .field("args", &"..")
73            .field("body", &"..")
74            .finish()
75    }
76}
77
78impl<T> Default for Function<T>
79where
80    T: Default,
81{
82    fn default() -> Self {
83        Self {
84            name: Ident("".to_string()),
85            args: vec![],
86            ret: T::default(),
87            body: T::default(),
88            doc: None,
89            is_async: false,
90            vis: Default::default(),
91            attributes: vec![],
92        }
93    }
94}
95
96/// Build something wrapped in braces, { A, B, C }
97pub fn build_struct(mut s: impl Iterator<Item = impl AsRef<str>>) -> String {
98    let mut r = String::from("{");
99    let mut t = s.next();
100    while let Some(u) = &t {
101        r.push_str(u.as_ref());
102        t = s.next();
103        if t.is_some() {
104            r.push_str(", ");
105        }
106    }
107    r.push('}');
108    r
109}
110
111/// Build keys wrapped in braces, e.g. {"a": 1, "b": 2}
112pub fn build_dict<'a>(s: impl Iterator<Item = (&'a str, &'a str)>) -> String {
113    build_struct(s.map(|(k, v)| format!("\"{}\": {}", k, v)))
114}