fn generate_params()

in yaml_test_runner/src/step/do.rs [364:615]


    fn generate_params(
        api: &Api,
        endpoint: &ApiEndpoint,
        params: &[(&str, &Yaml)],
    ) -> anyhow::Result<Option<Tokens>> {
        match params.len() {
            0 => Ok(None),
            _ => {
                let mut tokens = Tokens::new();
                for (n, v) in params {
                    let param_ident =
                        syn::Ident::from(api_generator::generator::code_gen::valid_name(n));

                    let ty = match endpoint.params.get(*n) {
                        Some(t) => Ok(t),
                        None => match api.common_params.get(*n) {
                            Some(t) => Ok(t),
                            None => Err(anyhow!(r#"no param found for "{}""#, n)),
                        },
                    }?;

                    let kind = &ty.ty;

                    match v {
                        Yaml::String(ref s) => {
                            let is_set_value = s.starts_with('$');

                            match kind {
                                TypeKind::Enum => {
                                    if n == &"expand_wildcards" {
                                        // expand_wildcards might be defined as a comma-separated
                                        // string. e.g.
                                        let idents: Vec<anyhow::Result<Tokens>> = s
                                            .split(',')
                                            .collect::<Vec<_>>()
                                            .iter()
                                            .map(|e| Self::generate_enum(n, e, &ty.options))
                                            .collect();

                                        match ok_or_accumulate(&idents) {
                                            Ok(_) => {
                                                let idents: Vec<Tokens> = idents
                                                    .into_iter()
                                                    .filter_map(Result::ok)
                                                    .collect();

                                                tokens.append(quote! {
                                                    .#param_ident(&[#(#idents),*])
                                                });
                                            }
                                            Err(e) => return Err(anyhow!(e)),
                                        }
                                    } else {
                                        let e = Self::generate_enum(n, s.as_str(), &ty.options)?;
                                        tokens.append(quote! {
                                            .#param_ident(#e)
                                        });
                                    }
                                }
                                TypeKind::List => {
                                    let values: Vec<&str> = s.split(',').collect();
                                    tokens.append(quote! {
                                        .#param_ident(&[#(#values),*])
                                    })
                                }
                                TypeKind::Boolean => match s.parse::<bool>() {
                                    Ok(b) => tokens.append(quote! {
                                        .#param_ident(#b)
                                    }),
                                    Err(e) => {
                                        return Err(anyhow!(
                                            r#"cannot parse bool from "{}" for param "{}", {}"#,
                                            s,
                                            n,
                                            e
                                        ))
                                    }
                                },
                                TypeKind::Double => match s.parse::<f64>() {
                                    Ok(f) => tokens.append(quote! {
                                        .#param_ident(#f)
                                    }),
                                    Err(e) => {
                                        return Err(anyhow!(
                                            r#"cannot parse f64 from "{}" for param "{}", {}"#,
                                            s,
                                            n,
                                            e
                                        ))
                                    }
                                },
                                TypeKind::Integer => {
                                    if is_set_value {
                                        let set_value = Self::from_set_value(s);
                                        tokens.append(quote! {
                                           .#param_ident(#set_value.as_i64().unwrap() as i32)
                                        });
                                    } else {
                                        match s.parse::<i32>() {
                                            Ok(i) => tokens.append(quote! {
                                                .#param_ident(#i)
                                            }),
                                            Err(e) => {
                                                return Err(anyhow!(
                                                    r#"cannot parse i32 from "{}" for param "{}", {}"#,
                                                    s,
                                                    n,
                                                    e
                                                ))
                                            }
                                        }
                                    }
                                }
                                TypeKind::Number | TypeKind::Long => {
                                    if is_set_value {
                                        let set_value = Self::from_set_value(s);
                                        tokens.append(quote! {
                                           .#param_ident(#set_value.as_i64().unwrap())
                                        });
                                    } else {
                                        let i = s.parse::<i64>()?;
                                        tokens.append(quote! {
                                            .#param_ident(#i)
                                        });
                                    }
                                }
                                _ => {
                                    // handle set values
                                    let t = if is_set_value {
                                        let set_value = Self::from_set_value(s);
                                        quote! { #set_value.as_str().unwrap() }
                                    } else {
                                        quote! { #s }
                                    };

                                    tokens.append(quote! {
                                        .#param_ident(#t)
                                    })
                                }
                            }
                        }
                        Yaml::Boolean(ref b) => match kind {
                            TypeKind::Enum => {
                                let enum_name = syn::Ident::from(n.to_pascal_case());
                                let variant = syn::Ident::from(b.to_string().to_pascal_case());
                                tokens.append(quote! {
                                    .#param_ident(#enum_name::#variant)
                                })
                            }
                            TypeKind::List => {
                                // TODO: _source filter can be true|false|list of strings
                                let s = b.to_string();
                                tokens.append(quote! {
                                    .#param_ident(&[#s])
                                })
                            }
                            _ => {
                                tokens.append(quote! {
                                    .#param_ident(#b)
                                });
                            }
                        },
                        Yaml::Integer(ref i) => match kind {
                            TypeKind::String => {
                                let s = i.to_string();
                                tokens.append(quote! {
                                    .#param_ident(#s)
                                })
                            }
                            TypeKind::Integer => {
                                // yaml-rust parses all as i64
                                let int = *i as i32;
                                tokens.append(quote! {
                                    .#param_ident(#int)
                                });
                            }
                            TypeKind::Float => {
                                // yaml-rust parses all as i64
                                let f = *i as f32;
                                tokens.append(quote! {
                                    .#param_ident(#f)
                                });
                            }
                            TypeKind::Double => {
                                // yaml-rust parses all as i64
                                let f = *i as f64;
                                tokens.append(quote! {
                                    .#param_ident(#f)
                                });
                            }
                            _ => {
                                tokens.append(quote! {
                                    .#param_ident(#i)
                                });
                            }
                        },
                        Yaml::Array(arr) => {
                            // only support param string arrays
                            let result: Vec<&String> = arr
                                .iter()
                                .map(|i| match i {
                                    Yaml::String(s) => Ok(s),
                                    y => Err(anyhow!("unsupported array value {:?}", y)),
                                })
                                .filter_map(Result::ok)
                                .collect();

                            if n == &"expand_wildcards" {
                                let result: Vec<anyhow::Result<Tokens>> = result
                                    .iter()
                                    .map(|s| Self::generate_enum(n, s.as_str(), &ty.options))
                                    .collect();

                                match ok_or_accumulate(&result) {
                                    Ok(_) => {
                                        let result: Vec<Tokens> =
                                            result.into_iter().filter_map(Result::ok).collect();

                                        tokens.append(quote! {
                                            .#param_ident(&[#(#result),*])
                                        });
                                    }
                                    Err(e) => return Err(anyhow!(e)),
                                }
                            } else {
                                tokens.append(quote! {
                                    .#param_ident(&[#(#result),*])
                                });
                            }
                        }
                        Yaml::Real(r) => match kind {
                            TypeKind::Long | TypeKind::Number => {
                                let f = r.parse::<f64>()?;
                                tokens.append(quote! {
                                    .#param_ident(#f as i64)
                                });
                            }
                            _ => {
                                let f = r.parse::<f64>()?;
                                tokens.append(quote! {
                                    .#param_ident(#f)
                                });
                            }
                        },
                        _ => println!("unsupported value {:?} for param {}", v, n),
                    }
                }

                Ok(Some(tokens))
            }
        }
    }