pmhelp_internal/exts/
is_exts.rs1use alloc::vec::Vec;
2use syn::{
3 parse::{Parse, ParseBuffer, Peek},
4 GenericArgument, Ident, Path, PathArguments, PathSegment, Type, TypePath,
5};
6
7#[derive(PartialEq, Clone, Copy)]
8enum OptionCheckerState {
9 Unknown = 1,
10 StdOrCore = 2,
11 OptionMod = 3,
12 Final = 4,
13}
14
15impl PartialEq<PathSegment> for OptionCheckerState {
16 fn eq(&self, PathSegment { ident, arguments }: &PathSegment) -> bool {
17 match self {
18 Self::StdOrCore => {
19 (ident == "std" || ident == "core") && matches!(arguments, PathArguments::None)
20 }
21 Self::OptionMod => ident == "option" && matches!(arguments, PathArguments::None),
22 Self::Final => ident == "Option" && !matches!(arguments, PathArguments::None),
23 Self::Unknown => true,
24 }
25 }
26}
27
28impl OptionCheckerState {
29 fn next_states(&self) -> &[Self] {
30 match self {
31 Self::Final => &[],
32 Self::OptionMod => &[Self::Final],
33 Self::StdOrCore => &[Self::OptionMod],
34 Self::Unknown => &[Self::OptionMod, Self::Final, Self::StdOrCore],
35 }
36 }
37}
38
39pub trait OptionTypeExt {
40 fn is_option(&self) -> bool;
41}
42
43impl OptionTypeExt for Path {
44 fn is_option(&self) -> bool {
45 let mut current_state = if self.leading_colon.is_some() {
46 OptionCheckerState::StdOrCore
47 } else {
48 OptionCheckerState::Unknown
49 };
50 for segment in self.segments.iter() {
51 let mut state_changed = false;
52 for state in current_state.next_states() {
53 if state == segment {
54 current_state = *state;
55 state_changed = true;
56 break;
57 }
58 }
59 if !state_changed {
60 return false;
61 }
62 }
63 current_state == OptionCheckerState::Final
64 }
65}
66
67impl OptionTypeExt for Type {
68 fn is_option(&self) -> bool {
69 if let Self::Path(TypePath { path, qself: None }) = &self {
70 path.is_option()
71 } else {
72 false
73 }
74 }
75}
76
77#[derive(PartialEq, Clone, Copy)]
78enum ResultCheckerState {
79 Unknown = 1,
80 StdOrCore = 2,
81 ResultMod = 3,
82 Final = 4,
83}
84
85impl PartialEq<PathSegment> for ResultCheckerState {
86 fn eq(&self, PathSegment { ident, arguments }: &PathSegment) -> bool {
87 match self {
88 Self::StdOrCore => {
89 (ident == "std" || ident == "core") && matches!(arguments, PathArguments::None)
90 }
91 Self::ResultMod => ident == "result" && matches!(arguments, PathArguments::None),
92 Self::Final => ident == "Result" && !matches!(arguments, PathArguments::None),
93 Self::Unknown => true,
94 }
95 }
96}
97
98impl ResultCheckerState {
99 fn next_states(&self) -> &[Self] {
100 match self {
101 Self::Final => &[],
102 Self::ResultMod => &[Self::Final],
103 Self::StdOrCore => &[Self::ResultMod],
104 Self::Unknown => &[Self::ResultMod, Self::Final, Self::StdOrCore],
105 }
106 }
107}
108
109pub trait ResultTypeExt {
110 fn is_result(&self) -> bool;
111}
112
113impl ResultTypeExt for Path {
114 fn is_result(&self) -> bool {
115 let mut current_state = if self.leading_colon.is_some() {
116 ResultCheckerState::StdOrCore
117 } else {
118 ResultCheckerState::Unknown
119 };
120 for segment in self.segments.iter() {
121 let mut state_changed = false;
122 for state in current_state.next_states() {
123 if state == segment {
124 current_state = *state;
125 state_changed = true;
126 break;
127 }
128 }
129 if !state_changed {
130 return false;
131 }
132 }
133 current_state == ResultCheckerState::Final
134 }
135}
136
137impl ResultTypeExt for Type {
138 fn is_result(&self) -> bool {
139 if let Self::Path(TypePath { path, qself: None }) = &self {
140 path.is_result()
141 } else {
142 false
143 }
144 }
145}