portrait_framework/
item_map.rs1use std::collections::HashMap;
2
3use syn::{Error, Result};
4
5pub fn subtract_items<'t>(
7 trait_items: &'t [syn::TraitItem],
8 impl_block: &'t syn::ItemImpl,
9) -> syn::Result<TraitItemMap<'t>> {
10 let mut items = TraitItemMap::new(trait_items);
11 items.minus(&ImplItemMap::new(impl_block))?;
12 Ok(items)
13}
14
15#[derive(Default)]
17pub struct TraitItemMap<'t> {
18 pub consts: HashMap<syn::Ident, &'t syn::TraitItemConst>,
20 pub fns: HashMap<syn::Ident, &'t syn::TraitItemFn>,
22 pub types: HashMap<syn::Ident, &'t syn::TraitItemType>,
24}
25
26impl<'t> TraitItemMap<'t> {
27 pub fn new(trait_items: &'t [syn::TraitItem]) -> Self {
29 let mut map = Self::default();
30 for item in trait_items {
31 match item {
32 syn::TraitItem::Const(item) => {
33 map.consts.insert(item.ident.clone(), item);
34 }
35 syn::TraitItem::Fn(item) => {
36 map.fns.insert(item.sig.ident.clone(), item);
37 }
38 syn::TraitItem::Type(item) => {
39 map.types.insert(item.ident.clone(), item);
40 }
41 _ => {}
42 }
43 }
44 map
45 }
46
47 pub fn minus(&mut self, impl_items: &ImplItemMap) -> Result<()> {
49 for (ident, impl_item) in &impl_items.consts {
50 if self.consts.remove(ident).is_none() {
51 return Err(Error::new_spanned(
52 impl_item,
53 "no associated constant called {ident} in trait",
54 ));
55 }
56 }
57
58 for (ident, impl_item) in &impl_items.fns {
59 if self.fns.remove(ident).is_none() {
60 return Err(Error::new_spanned(
61 impl_item,
62 "no associated function called {ident} in trait",
63 ));
64 }
65 }
66
67 for (ident, impl_item) in &impl_items.types {
68 if self.types.remove(ident).is_none() {
69 return Err(Error::new_spanned(
70 impl_item,
71 "no associated type called {ident} in trait",
72 ));
73 }
74 }
75
76 Ok(())
77 }
78}
79
80#[derive(Default)]
82pub struct ImplItemMap<'t> {
83 pub consts: HashMap<syn::Ident, &'t syn::ImplItemConst>,
85 pub fns: HashMap<syn::Ident, &'t syn::ImplItemFn>,
87 pub types: HashMap<syn::Ident, &'t syn::ImplItemType>,
89}
90
91impl<'t> ImplItemMap<'t> {
92 pub fn new(impl_block: &'t syn::ItemImpl) -> Self {
94 let mut map = Self::default();
95 for item in &impl_block.items {
96 match item {
97 syn::ImplItem::Const(item) => {
98 map.consts.insert(item.ident.clone(), item);
99 }
100 syn::ImplItem::Fn(item) => {
101 map.fns.insert(item.sig.ident.clone(), item);
102 }
103 syn::ImplItem::Type(item) => {
104 map.types.insert(item.ident.clone(), item);
105 }
106 _ => {}
107 }
108 }
109 map
110 }
111}