ty_ext.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. use crate::ASTResult;
  2. use syn::{self, AngleBracketedGenericArguments, PathSegment};
  3. #[derive(Eq, PartialEq, Debug)]
  4. pub enum PrimitiveTy {
  5. Map(MapInfo),
  6. Vec,
  7. Opt,
  8. Other,
  9. }
  10. #[derive(Debug)]
  11. pub struct TyInfo<'a> {
  12. pub ident: &'a syn::Ident,
  13. pub ty: &'a syn::Type,
  14. pub primitive_ty: PrimitiveTy,
  15. pub bracket_ty_info: Box<Option<TyInfo<'a>>>,
  16. }
  17. #[derive(Debug, Eq, PartialEq)]
  18. pub struct MapInfo {
  19. pub key: String,
  20. pub value: String,
  21. }
  22. impl MapInfo {
  23. fn new(key: String, value: String) -> Self {
  24. MapInfo { key, value }
  25. }
  26. }
  27. impl<'a> TyInfo<'a> {
  28. #[allow(dead_code)]
  29. pub fn bracketed_ident(&'a self) -> &'a syn::Ident {
  30. match self.bracket_ty_info.as_ref() {
  31. Some(b_ty) => b_ty.ident,
  32. None => {
  33. panic!()
  34. },
  35. }
  36. }
  37. }
  38. pub fn parse_ty<'a>(
  39. ast_result: &ASTResult,
  40. ty: &'a syn::Type,
  41. ) -> Result<Option<TyInfo<'a>>, String> {
  42. // Type -> TypePath -> Path -> PathSegment -> PathArguments ->
  43. // AngleBracketedGenericArguments -> GenericArgument -> Type.
  44. if let syn::Type::Path(ref p) = ty {
  45. if p.path.segments.len() != 1 {
  46. return Ok(None);
  47. }
  48. let seg = match p.path.segments.last() {
  49. Some(seg) => seg,
  50. None => return Ok(None),
  51. };
  52. let _is_option = seg.ident == "Option";
  53. return if let syn::PathArguments::AngleBracketed(ref bracketed) = seg.arguments {
  54. match seg.ident.to_string().as_ref() {
  55. "HashMap" => generate_hashmap_ty_info(ast_result, ty, seg, bracketed),
  56. "Vec" => generate_vec_ty_info(ast_result, seg, bracketed),
  57. "Option" => generate_option_ty_info(ast_result, ty, seg, bracketed),
  58. _ => {
  59. let msg = format!("Unsupported type: {}", seg.ident);
  60. ast_result.error_spanned_by(&seg.ident, &msg);
  61. return Err(msg);
  62. },
  63. }
  64. } else {
  65. return Ok(Some(TyInfo {
  66. ident: &seg.ident,
  67. ty,
  68. primitive_ty: PrimitiveTy::Other,
  69. bracket_ty_info: Box::new(None),
  70. }));
  71. };
  72. }
  73. Err("Unsupported inner type, get inner type fail".to_string())
  74. }
  75. fn parse_bracketed(bracketed: &AngleBracketedGenericArguments) -> Vec<&syn::Type> {
  76. bracketed
  77. .args
  78. .iter()
  79. .flat_map(|arg| {
  80. if let syn::GenericArgument::Type(ref ty_in_bracket) = arg {
  81. Some(ty_in_bracket)
  82. } else {
  83. None
  84. }
  85. })
  86. .collect::<Vec<&syn::Type>>()
  87. }
  88. pub fn generate_hashmap_ty_info<'a>(
  89. ast_result: &ASTResult,
  90. ty: &'a syn::Type,
  91. path_segment: &'a PathSegment,
  92. bracketed: &'a AngleBracketedGenericArguments,
  93. ) -> Result<Option<TyInfo<'a>>, String> {
  94. // The args of map must greater than 2
  95. if bracketed.args.len() != 2 {
  96. return Ok(None);
  97. }
  98. let types = parse_bracketed(bracketed);
  99. let key = parse_ty(ast_result, types[0])?.unwrap().ident.to_string();
  100. let value = parse_ty(ast_result, types[1])?.unwrap().ident.to_string();
  101. let bracket_ty_info = Box::new(parse_ty(ast_result, types[1])?);
  102. Ok(Some(TyInfo {
  103. ident: &path_segment.ident,
  104. ty,
  105. primitive_ty: PrimitiveTy::Map(MapInfo::new(key, value)),
  106. bracket_ty_info,
  107. }))
  108. }
  109. fn generate_option_ty_info<'a>(
  110. ast_result: &ASTResult,
  111. ty: &'a syn::Type,
  112. path_segment: &'a PathSegment,
  113. bracketed: &'a AngleBracketedGenericArguments,
  114. ) -> Result<Option<TyInfo<'a>>, String> {
  115. assert_eq!(path_segment.ident.to_string(), "Option".to_string());
  116. let types = parse_bracketed(bracketed);
  117. let bracket_ty_info = Box::new(parse_ty(ast_result, types[0])?);
  118. Ok(Some(TyInfo {
  119. ident: &path_segment.ident,
  120. ty,
  121. primitive_ty: PrimitiveTy::Opt,
  122. bracket_ty_info,
  123. }))
  124. }
  125. fn generate_vec_ty_info<'a>(
  126. ast_result: &ASTResult,
  127. path_segment: &'a PathSegment,
  128. bracketed: &'a AngleBracketedGenericArguments,
  129. ) -> Result<Option<TyInfo<'a>>, String> {
  130. if bracketed.args.len() != 1 {
  131. return Ok(None);
  132. }
  133. if let syn::GenericArgument::Type(ref bracketed_type) = bracketed.args.first().unwrap() {
  134. let bracketed_ty_info = Box::new(parse_ty(ast_result, bracketed_type)?);
  135. return Ok(Some(TyInfo {
  136. ident: &path_segment.ident,
  137. ty: bracketed_type,
  138. primitive_ty: PrimitiveTy::Vec,
  139. bracket_ty_info: bracketed_ty_info,
  140. }));
  141. }
  142. Ok(None)
  143. }