1#![deny(missing_docs)]
13#![allow(clippy::unnecessary_lazy_evaluations)]
15#![allow(clippy::style)]
16
17pub mod anon;
18pub mod autoimpl;
19mod default;
20pub mod fields;
21pub mod generics;
22pub mod scope;
23mod split_impl;
24mod utils;
25
26pub use default::ImplDefault;
27pub use split_impl::SplitImpl;
28
29use proc_macro2::Span;
30use syn::Ident;
31
32pub struct IdentFormatter(String);
34impl IdentFormatter {
35 pub fn new() -> Self {
37 IdentFormatter(String::with_capacity(32))
38 }
39
40 pub fn make(&mut self, args: std::fmt::Arguments, span: Span) -> Ident {
42 use std::fmt::Write;
43
44 self.0.clear();
45 self.0.write_fmt(args).unwrap();
46 Ident::new(&self.0, span)
47 }
48
49 #[inline]
60 pub fn make_call_site(&mut self, args: std::fmt::Arguments) -> Ident {
61 self.make(args, Span::call_site())
62 }
63}
64
65#[derive(PartialEq, Eq)]
67pub struct SimplePath(&'static [&'static str]);
68
69impl std::fmt::Display for SimplePath {
70 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
71 if !self.0.is_empty() {
72 write!(f, "{}", self.0[0])?;
73 for component in &self.0[1..] {
74 write!(f, "::{}", component)?;
75 }
76 }
77
78 Ok(())
79 }
80}
81
82impl SimplePath {
83 pub fn new(path: &'static [&'static str]) -> Self {
91 let mut is_empty = false;
92 for (i, s) in path.iter().enumerate() {
93 is_empty = is_empty && s.is_empty();
94 if i > 0 && s.is_empty() {
95 panic!("empty component");
96 }
97 }
98 if is_empty {
99 panic!("empty path");
100 }
101 SimplePath(path)
102 }
103
104 pub fn matches(&self, path: &syn::Path) -> bool {
113 let mut q = self.0;
114 assert!(!q.is_empty());
115 if path.leading_colon.is_some() && !q[0].is_empty() {
116 return false;
117 }
118 if q[0].is_empty() {
119 q = &q[1..];
120 }
121
122 if path.segments.len() != q.len() {
123 return false;
124 }
125
126 let mut first = true;
127 for (x, y) in path.segments.iter().zip(q.iter()) {
128 if !x.arguments.is_empty() {
129 return false;
130 }
131
132 #[allow(clippy::if_same_then_else)]
133 if x.ident == y {
134 } else if first && (*y == "core" || *y == "alloc") && x.ident == "std" {
135 } else {
136 return false;
137 }
138
139 first = false;
140 }
141
142 true
143 }
144
145 pub fn matches_ident(&self, ident: &syn::Ident) -> bool {
147 assert!(!self.0.is_empty());
148 self.0.iter().last().map(|s| ident == s).unwrap_or(false)
149 }
150
151 pub fn matches_ident_or_path(&self, path: &syn::Path) -> bool {
155 if path.leading_colon.is_none() && path.segments.len() == 1 {
156 let seg = &path.segments[0];
157 seg.arguments.is_empty() && self.matches_ident(&seg.ident)
158 } else {
159 self.matches(path)
160 }
161 }
162}
163
164fn error_on_attrs(attrs: &[syn::Attribute]) {
167 use proc_macro_error3::emit_error;
168 for attr in attrs.iter() {
169 emit_error!(attr, "attributes are not (yet) supported in this context");
170 }
171}