use serde_yaml::{from_str, Value};
use syn::punctuated::Pair;
use syn::token::Colon2;
use syn::{GenericArgument, Path, PathArguments, PathSegment};
use std::collections::HashMap;
use std::fs;
use tracing;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::{fmt, EnvFilter};
pub fn read_file(filename: &str) -> Vec<HashMap<String, Value>> {
let s = fs::read_to_string(filename).unwrap();
s.split("\n---\n")
.filter(|x| x.len() > 0)
.map(|x| from_str(x).unwrap())
.collect()
}
pub fn get_raw_objects_of_type(
raw_objects: &Vec<HashMap<String, Value>>,
object_type: String,
) -> Vec<HashMap<String, Value>> {
raw_objects
.into_iter()
.filter(|x| x.get("type").unwrap().as_str().unwrap() == object_type)
.map(|x| {
x.get("spec")
.unwrap()
.as_mapping()
.unwrap()
.into_iter()
.map(|(k, v)| (k.as_str().unwrap().into(), v.clone()))
.collect()
})
.collect::<Vec<HashMap<String, Value>>>()
}
pub fn init_logging() {
let filter_layer = EnvFilter::try_from_env("LOG_LEVEL")
.or_else(|_| EnvFilter::try_new("info"))
.expect("Failed to initialize filter layer");
tracing::subscriber::set_global_default(
tracing_subscriber::Registry::default()
.with(filter_layer)
.with(fmt::layer()),
)
.expect("Failed to set default subscriber");
}
pub fn extract_type_path(ty: &syn::Type) -> Option<&Path> {
match *ty {
syn::Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path),
_ => None,
}
}
fn get_inner_type<'a>(
ty: &'a syn::Type,
idents: Vec<String>,
) -> Option<Pair<&'a PathSegment, &'a Colon2>> {
let extract_option_segment = |path: &'a Path| -> Option<Pair<&'a PathSegment, &'a Colon2>> {
let idents_of_path = path
.segments
.iter()
.into_iter()
.fold(String::new(), |mut acc, v| {
acc.push_str(&v.ident.to_string());
acc.push('|');
acc
});
idents
.into_iter()
.find(|s| idents_of_path == *s)
.and_then(|_| path.segments.last())
.map(Pair::End)
};
let tp = extract_type_path(&ty);
tp.and_then(|path| extract_option_segment(path))
}
fn extract_inner_from_bracketed_type<'a>(
ty: &'a syn::Type,
idents: Vec<String>,
) -> Option<&'a syn::Type> {
let tp2 = get_inner_type(ty, idents);
let tp3 = tp2.and_then(|pair_path_segment| {
let type_params = &pair_path_segment.into_value().arguments;
match *type_params {
PathArguments::AngleBracketed(ref params) => params.args.first(),
_ => None,
}
});
tp3.and_then(|generic_arg| match *generic_arg {
GenericArgument::Type(ref ty) => Some(ty),
_ => None,
})
}
fn extract_inner_from_double_bracketed_type<'a>(
ty: &'a syn::Type,
idents: Vec<String>,
) -> Option<(&'a syn::Type, &'a syn::Type)> {
let tp2 = get_inner_type(ty, idents);
let tp3 = tp2.and_then(|pair_path_segment| {
let type_params = &pair_path_segment.into_value().arguments;
match *type_params {
PathArguments::AngleBracketed(ref params) => {
assert_eq!(params.args.len(), 2);
let mut it = params.args.iter();
let first = it.next().unwrap();
let second = it.next().unwrap();
Some((first, second))
}
_ => None,
}
});
tp3.and_then(|generic_arg| match generic_arg {
(&GenericArgument::Type(ref ty1), &GenericArgument::Type(ref ty2)) => Some((ty1, ty2)),
_ => None,
})
}
pub fn extract_type_from_option(ty: &syn::Type) -> Option<&syn::Type> {
extract_inner_from_bracketed_type(
ty,
vec![
"Option|".to_string(),
"std|option|Option|".into(),
"core|option|Option|".into(),
],
)
}
pub fn extract_type_from_vector(ty: &syn::Type) -> Option<&syn::Type> {
extract_inner_from_bracketed_type(
ty,
vec![
"Vector|".to_string(),
"std|vec|Vec|".into(),
"Vec|".to_string(),
],
)
}
pub fn extract_type_from_map(ty: &syn::Type) -> Option<(&syn::Type, &syn::Type)> {
extract_inner_from_double_bracketed_type(
ty,
vec![
"BTreeMap|".to_string(),
"std|collections|BTreeMap|".into(),
],
)
}
pub fn extract_type_from_linked_hash_map(ty: &syn::Type) -> Option<(&syn::Type, &syn::Type)> {
extract_inner_from_double_bracketed_type(
ty,
vec![
"LinkedHashMap|".to_string(),
"linked_hash_map|LinkedHashMap|".into(),
],
)
}
pub fn extract_type_from_aorist_ref(ty: &syn::Type) -> Option<&syn::Type> {
extract_inner_from_bracketed_type(
ty,
vec![
"Arc|".to_string(),
"AoristRef|".to_string(),
],
)
}