use dashmap::{DashMap, DashSet}; use flowy_ast::{Ctxt, TyInfo}; use lazy_static::lazy_static; use lib_infra::proto_gen::ProtoCache; use std::fs::File; use std::io::Read; use std::sync::atomic::{AtomicBool, Ordering}; use walkdir::WalkDir; pub fn ident_category(ident: &syn::Ident) -> TypeCategory { let ident_str = ident.to_string(); category_from_str(ident_str) } pub(crate) fn get_member_ident<'a>(ctxt: &Ctxt, member: &'a syn::Member) -> Option<&'a syn::Ident> { if let syn::Member::Named(ref ident) = member { Some(ident) } else { ctxt.error_spanned_by(member, "Unsupported member, shouldn't be self.0".to_string()); None } } pub fn assert_bracket_ty_is_some(ctxt: &Ctxt, ty_info: &TyInfo) { if ty_info.bracket_ty_info.is_none() { ctxt.error_spanned_by(ty_info.ty, "Invalid bracketed type when gen de token steam".to_string()); } } lazy_static! { static ref READ_FLAG: DashSet = DashSet::new(); static ref CACHE_INFO: DashMap> = DashMap::new(); static ref IS_LOAD: AtomicBool = AtomicBool::new(false); } #[derive(Eq, Hash, PartialEq)] pub enum TypeCategory { Array, Map, Str, Protobuf, Bytes, Enum, Opt, Primitive, } // auto generate, do not edit pub fn category_from_str(type_str: String) -> TypeCategory { if !IS_LOAD.load(Ordering::SeqCst) { IS_LOAD.store(true, Ordering::SeqCst); // Dependents on another crate file is not good, just leave it here. // Maybe find another way to read the .cache in the future. let cache_dir = format!("{}/../lib-infra/.cache", env!("CARGO_MANIFEST_DIR")); for path in WalkDir::new(cache_dir) .into_iter() .filter_map(|e| e.ok()) .map(|e| e.path().to_str().unwrap().to_string()) { match read_file(&path) { None => {} Some(s) => { let cache: ProtoCache = serde_json::from_str(&s).unwrap(); CACHE_INFO .entry(TypeCategory::Protobuf) .or_insert(vec![]) .extend(cache.structs); CACHE_INFO .entry(TypeCategory::Enum) .or_insert(vec![]) .extend(cache.enums); } } } } if let Some(protobuf) = CACHE_INFO.get(&TypeCategory::Protobuf) { if protobuf.contains(&type_str) { return TypeCategory::Protobuf; } } if let Some(protobuf) = CACHE_INFO.get(&TypeCategory::Enum) { if protobuf.contains(&type_str) { return TypeCategory::Enum; } } match type_str.as_str() { "Vec" => TypeCategory::Array, "HashMap" => TypeCategory::Map, "u8" => TypeCategory::Bytes, "String" => TypeCategory::Str, "Option" => TypeCategory::Opt, _ => TypeCategory::Primitive, } } fn read_file(path: &str) -> Option { match File::open(path) { Ok(mut file) => { let mut content = String::new(); match file.read_to_string(&mut content) { Ok(_) => Some(content), Err(_) => None, } } Err(_) => None, } }