@@ -8,16 +8,6 @@ use rustc_span::sym;
88
99use super :: IP_CONSTANT ;
1010
11- static IPV4V6_CONSTANTS : & [ ( & [ u128 ] , & str ) ] = & [
12- // Ipv4
13- ( & [ 127 , 0 , 0 , 1 ] , "LOCALHOST" ) ,
14- ( & [ 255 , 255 , 255 , 255 ] , "BROADCAST" ) ,
15- ( & [ 0 , 0 , 0 , 0 ] , "UNSPECIFIED" ) ,
16- // Ipv6
17- ( & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] , "LOCALHOST" ) ,
18- ( & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , "UNSPECIFIED" ) ,
19- ] ;
20-
2111pub ( super ) fn check ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , func : & Expr < ' _ > , args : & [ Expr < ' _ > ] ) {
2212 if let ExprKind :: Path ( QPath :: TypeRelative (
2313 Ty {
@@ -30,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args
3020 && let Some ( func_def_id) = func_path. res . opt_def_id ( )
3121 && ( cx. tcx . is_diagnostic_item ( sym:: Ipv4Addr , func_def_id)
3222 || cx. tcx . is_diagnostic_item ( sym:: Ipv6Addr , func_def_id) )
33- && let Some ( constant_name) = is_ipv4v6_constants ( cx, args)
23+ && let Some ( constant_name) = is_ipaddr_constants ( cx, args)
3424 {
3525 let sugg_snip = format ! (
3626 "{}::{}" ,
@@ -50,7 +40,63 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args
5040 }
5141}
5242
53- fn is_ipv4v6_constants ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] ) -> Option < & ' static str > {
43+ struct Node {
44+ children : & ' static [ ( u128 , Node ) ] ,
45+ constant_name : Option < & ' static str > ,
46+ }
47+
48+ impl Node {
49+ const fn new ( children : & ' static [ ( u128 , Node ) ] , constant_name : Option < & ' static str > ) -> Self {
50+ Self {
51+ children,
52+ constant_name,
53+ }
54+ }
55+
56+ const fn leaf ( constant_name : & ' static str ) -> Self {
57+ Self {
58+ children : & [ ] ,
59+ constant_name : Some ( constant_name) ,
60+ }
61+ }
62+ }
63+
64+ // Tree structure for IP constants
65+ #[ rustfmt:: skip]
66+ static IPADDR_CONSTANTS_TREE : Node = Node :: new ( & [
67+ ( 127 , Node :: new ( & [
68+ ( 0 , Node :: new ( & [
69+ ( 0 , Node :: new ( & [
70+ ( 1 , Node :: leaf ( "LOCALHOST" ) ) // IPv4 127.0.0.1
71+ ] , None ) )
72+ ] , None ) )
73+ ] , None ) ) ,
74+ ( 255 , Node :: new ( & [
75+ ( 255 , Node :: new ( & [
76+ ( 255 , Node :: new ( & [
77+ ( 255 , Node :: leaf ( "BROADCAST" ) ) // IPv4 255.255.255.255
78+ ] , None ) )
79+ ] , None ) )
80+ ] , None ) ) ,
81+ ( 0 , Node :: new ( & [
82+ ( 0 , Node :: new ( & [
83+ ( 0 , Node :: new ( & [
84+ ( 0 , Node :: new ( & [
85+ ( 0 , Node :: new ( & [
86+ ( 0 , Node :: new ( & [
87+ ( 0 , Node :: new ( & [
88+ ( 0 , Node :: leaf ( "UNSPECIFIED" ) ) , // IPv6 ::
89+ ( 1 , Node :: leaf ( "LOCALHOST" ) ) // IPv6 ::1
90+ ] , None ) )
91+ ] , None ) )
92+ ] , None ) )
93+ ] , Some ( "UNSPECIFIED" ) ) ) // IPv4 0.0.0.0
94+ ] , None ) )
95+ ] , None ) )
96+ ] , None ) ) ,
97+ ] , None ) ;
98+
99+ fn is_ipaddr_constants ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] ) -> Option < & ' static str > {
54100 if args. len ( ) != 4 && args. len ( ) != 8 {
55101 return None ;
56102 }
@@ -64,12 +110,15 @@ fn is_ipv4v6_constants(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<&'stat
64110 return None ;
65111 }
66112 }
67- // Check against known IP constants
68- for ( pattern, name) in IPV4V6_CONSTANTS {
69- if pattern. len ( ) == constants. len ( ) && pattern. iter ( ) . eq ( constants. iter ( ) ) {
70- return Some ( name) ;
113+
114+ let mut current_node = & IPADDR_CONSTANTS_TREE ;
115+ for value in constants {
116+ if let Some ( ( _, next_node) ) = current_node. children . iter ( ) . find ( |( val, _) | * val == value) {
117+ current_node = next_node;
118+ } else {
119+ return None ; // Early termination on mismatch
71120 }
72121 }
73122
74- None
123+ current_node . constant_name
75124}
0 commit comments