ruggle_engine/query/
mod.rs

1use std::{
2    collections::HashSet,
3    fmt::{self, Display},
4};
5
6use serde::{Deserialize, Serialize};
7
8pub mod parse;
9
10#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
11pub struct HitItem {
12    pub path: Vec<String>,
13    pub link: Vec<String>,
14    pub docs: Option<String>,
15}
16
17#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
18pub struct Query {
19    pub name: Option<Symbol>,
20    pub kind: Option<QueryKind>,
21}
22
23impl Query {
24    pub fn args(&self) -> Option<Vec<Argument>> {
25        self.kind
26            .as_ref()
27            .map(|kind| {
28                let QueryKind::FunctionQuery(f) = kind;
29                &f.decl
30            })
31            .and_then(|decl| decl.inputs.clone())
32    }
33}
34
35impl Display for Query {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(f, "fn")?;
38        if let Some(name) = &self.name {
39            write!(f, " {}", name)?;
40        }
41        if let Some(kind) = &self.kind {
42            match kind {
43                QueryKind::FunctionQuery(func) => {
44                    write!(f, "{}", func.decl)?;
45                }
46            }
47        }
48        Ok(())
49    }
50}
51
52#[non_exhaustive]
53#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
54pub enum QueryKind {
55    FunctionQuery(Function),
56}
57
58#[non_exhaustive]
59#[derive(Clone, Debug, Eq, Hash, Serialize, Deserialize, PartialEq)]
60pub enum Qualifier {
61    Async,
62    Unsafe,
63    Const,
64}
65
66#[non_exhaustive]
67#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
68pub struct Function {
69    pub decl: FnDecl,
70    pub qualifiers: HashSet<Qualifier>,
71}
72
73impl Display for FnDecl {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        write!(f, "(")?;
76        if let Some(inputs) = &self.inputs {
77            let input_strs: Vec<String> = inputs
78                .iter()
79                .map(|arg| match (&arg.name, &arg.ty) {
80                    (Some(name), Some(ty)) => format!("{}: {}", name, ty),
81                    (Some(name), None) => format!("{}: _", name),
82                    (None, Some(ty)) => format!("{}", ty),
83                    (None, None) => "_".to_string(),
84                })
85                .collect();
86            write!(f, "{}", input_strs.join(", "))?;
87        } else {
88            write!(f, "..")?;
89        }
90        write!(f, ")")?;
91        if let Some(output) = &self.output {
92            match output {
93                FnRetTy::Return(ty) => write!(f, " -> {}", ty)?,
94                FnRetTy::DefaultReturn => {}
95            }
96        }
97        Ok(())
98    }
99}
100
101#[non_exhaustive]
102#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
103pub enum GenericArgs {
104    AngleBracketed {
105        args: Vec<Option<GenericArg>>, /* bindings: Vec<TypeBinding> */
106    },
107    // Parenthesized { inputs: Vec<Type>, output: Option<Type> },
108}
109
110#[non_exhaustive]
111#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
112pub enum GenericArg {
113    // Lifetime(String),
114    Type(Type),
115    // Const(Constant),
116}
117#[non_exhaustive]
118#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
119pub struct FnDecl {
120    pub inputs: Option<Vec<Argument>>,
121    pub output: Option<FnRetTy>,
122    // pub c_variadic: bool,
123}
124
125#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
126pub struct Argument {
127    pub ty: Option<Type>,
128    pub name: Option<Symbol>,
129}
130
131#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
132pub enum FnRetTy {
133    Return(Type),
134    DefaultReturn,
135}
136
137pub type Symbol = String;
138
139#[non_exhaustive]
140#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
141pub enum Type {
142    // FIXME: Give `UnresolvedPath` a better name.
143    UnresolvedPath {
144        name: Symbol,
145        args: Option<Box<GenericArgs>>,
146    },
147    Generic(String),
148    Primitive(PrimitiveType),
149    Tuple(Vec<Option<Type>>),
150    Slice(Option<Box<Type>>),
151    Never,
152    RawPointer {
153        mutable: bool,
154        type_: Box<Type>,
155    },
156    BorrowedRef {
157        mutable: bool,
158        type_: Box<Type>,
159    },
160}
161
162impl Display for Type {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        use Type::*;
165        match self {
166            UnresolvedPath { name, args } => {
167                if let Some(args) = args {
168                    write!(f, "{}<{:?}>", name, args)
169                } else {
170                    write!(f, "{}", name)
171                }
172            }
173            Generic(name) => write!(f, "{}", name),
174            Primitive(prim) => write!(f, "{}", prim.as_str()),
175            Tuple(types) => {
176                let types: Vec<String> = types
177                    .iter()
178                    .map(|ty| match ty {
179                        Some(ty) => format!("{}", ty),
180                        None => "_".to_string(),
181                    })
182                    .collect();
183                write!(f, "({})", types.join(", "))
184            }
185            Slice(ty) => match ty {
186                Some(ty) => write!(f, "[{}]", ty),
187                None => write!(f, "[_]",),
188            },
189            Never => write!(f, "!"),
190            RawPointer { mutable, type_ } => {
191                if *mutable {
192                    write!(f, "*mut {}", type_)
193                } else {
194                    write!(f, "*const {}", type_)
195                }
196            }
197            BorrowedRef { mutable, type_ } => {
198                if *mutable {
199                    write!(f, "&mut {}", type_)
200                } else {
201                    write!(f, "&{}", type_)
202                }
203            }
204        }
205    }
206}
207
208impl Type {
209    pub fn inner_type(&self) -> &Self {
210        match self {
211            Type::RawPointer { type_, .. } => type_.inner_type(),
212            Type::BorrowedRef { type_, .. } => type_.inner_type(),
213            _ => self,
214        }
215    }
216}
217
218/// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
219/// paths, like `Unit`.
220#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
221pub enum PrimitiveType {
222    Isize,
223    I8,
224    I16,
225    I32,
226    I64,
227    I128,
228    Usize,
229    U8,
230    U16,
231    U32,
232    U64,
233    U128,
234    F32,
235    F64,
236    Char,
237    Bool,
238    Str,
239    Unit,
240    Never,
241}
242
243impl PrimitiveType {
244    pub fn as_str(&self) -> &str {
245        use PrimitiveType::*;
246        match self {
247            Isize => "isize",
248            I8 => "i8",
249            I16 => "i16",
250            I32 => "i32",
251            I64 => "i64",
252            I128 => "i128",
253            Usize => "usize",
254            U8 => "u8",
255            U16 => "u16",
256            U32 => "u32",
257            U64 => "u64",
258            U128 => "u128",
259            F32 => "f32",
260            F64 => "f64",
261            Char => "char",
262            Bool => "bool",
263            Str => "str",
264            Unit => "unit",
265            Never => "never",
266        }
267    }
268}