@@ -3,6 +3,113 @@ use crate::version::zerv::{
33 Component , PreReleaseVar , Zerv , ZervSchema , ZervVars , normalize_pre_release_label,
44} ;
55
6+ type ProcessResult = (
7+ Option < PreReleaseVar > ,
8+ Vec < Component > ,
9+ Option < u64 > ,
10+ Option < u64 > ,
11+ Option < u64 > ,
12+ ) ;
13+
14+ struct PreReleaseProcessor {
15+ pre_release : Option < PreReleaseVar > ,
16+ extra_core : Vec < Component > ,
17+ epoch : Option < u64 > ,
18+ post : Option < u64 > ,
19+ dev : Option < u64 > ,
20+ }
21+
22+ impl PreReleaseProcessor {
23+ fn new ( ) -> Self {
24+ Self {
25+ pre_release : None ,
26+ extra_core : Vec :: new ( ) ,
27+ epoch : None ,
28+ post : None ,
29+ dev : None ,
30+ }
31+ }
32+
33+ fn try_special_pattern ( & mut self , pr : & [ PreReleaseIdentifier ] , i : usize ) -> bool {
34+ if i + 1 >= pr. len ( ) {
35+ return false ;
36+ }
37+
38+ if let ( PreReleaseIdentifier :: String ( label) , PreReleaseIdentifier :: Integer ( num) ) =
39+ ( & pr[ i] , & pr[ i + 1 ] )
40+ {
41+ match label. as_str ( ) {
42+ "epoch" if self . epoch . is_none ( ) => {
43+ self . epoch = Some ( * num) ;
44+ self . extra_core
45+ . push ( Component :: VarField ( "epoch" . to_string ( ) ) ) ;
46+ true
47+ }
48+ "dev" if self . dev . is_none ( ) => {
49+ self . dev = Some ( * num) ;
50+ self . extra_core . push ( Component :: VarField ( "dev" . to_string ( ) ) ) ;
51+ true
52+ }
53+ "post" if self . post . is_none ( ) => {
54+ self . post = Some ( * num) ;
55+ self . extra_core
56+ . push ( Component :: VarField ( "post" . to_string ( ) ) ) ;
57+ true
58+ }
59+ _ => self . try_pre_release_pattern ( label, Some ( * num) ) ,
60+ }
61+ } else {
62+ false
63+ }
64+ }
65+
66+ fn try_pre_release_pattern ( & mut self , label : & str , number : Option < u64 > ) -> bool {
67+ if let Some ( normalized_label) = normalize_pre_release_label ( label)
68+ && self . pre_release . is_none ( )
69+ {
70+ self . pre_release = Some ( PreReleaseVar {
71+ label : normalized_label,
72+ number,
73+ } ) ;
74+ self . extra_core
75+ . push ( Component :: VarField ( "pre_release" . to_string ( ) ) ) ;
76+ return true ;
77+ }
78+ false
79+ }
80+
81+ fn add_regular_component ( & mut self , item : & PreReleaseIdentifier ) {
82+ self . extra_core . push ( match item {
83+ PreReleaseIdentifier :: String ( s) => Component :: String ( s. clone ( ) ) ,
84+ PreReleaseIdentifier :: Integer ( n) => Component :: Integer ( * n) ,
85+ } ) ;
86+ }
87+
88+ fn process ( mut self , pr : & [ PreReleaseIdentifier ] ) -> ProcessResult {
89+ let mut i = 0 ;
90+ while i < pr. len ( ) {
91+ if self . try_special_pattern ( pr, i) {
92+ i += 2 ;
93+ } else if let PreReleaseIdentifier :: String ( label) = & pr[ i] {
94+ if !self . try_pre_release_pattern ( label, None ) {
95+ self . add_regular_component ( & pr[ i] ) ;
96+ }
97+ i += 1 ;
98+ } else {
99+ self . add_regular_component ( & pr[ i] ) ;
100+ i += 1 ;
101+ }
102+ }
103+ (
104+ self . pre_release ,
105+ self . extra_core ,
106+ self . epoch ,
107+ self . post ,
108+ self . dev ,
109+ )
110+ }
111+ }
112+
6113impl From < SemVer > for Zerv {
7114 fn from ( semver : SemVer ) -> Self {
8115 let build = semver
@@ -19,99 +126,11 @@ impl From<SemVer> for Zerv {
19126 } )
20127 . unwrap_or_default ( ) ;
21128
22- let ( pre_release, extra_core, epoch, post, dev) = if let Some ( pr) = & semver. pre_release {
23- let mut pre_release = None ;
24- let mut extra_core = Vec :: new ( ) ;
25- let mut epoch = None ;
26- let mut post = None ;
27- let mut dev = None ;
28- let mut skip_next = false ;
29-
30- for ( i, item) in pr. iter ( ) . enumerate ( ) {
31- if skip_next {
32- skip_next = false ;
33- continue ;
34- }
35-
36- // Check for epoch+number pattern
37- if i + 1 < pr. len ( )
38- && let ( PreReleaseIdentifier :: String ( label) , PreReleaseIdentifier :: Integer ( num) ) =
39- ( item, & pr[ i + 1 ] )
40- && label == "epoch"
41- && epoch. is_none ( )
42- {
43- epoch = Some ( * num) ;
44- extra_core. push ( Component :: VarField ( "epoch" . to_string ( ) ) ) ;
45- skip_next = true ;
46- continue ;
47- }
48-
49- // Check for dev+number pattern
50- if i + 1 < pr. len ( )
51- && let ( PreReleaseIdentifier :: String ( label) , PreReleaseIdentifier :: Integer ( num) ) =
52- ( item, & pr[ i + 1 ] )
53- && label == "dev"
54- && dev. is_none ( )
55- {
56- dev = Some ( * num) ;
57- extra_core. push ( Component :: VarField ( "dev" . to_string ( ) ) ) ;
58- skip_next = true ;
59- continue ;
60- }
61-
62- // Check for post+number pattern
63- if i + 1 < pr. len ( )
64- && let ( PreReleaseIdentifier :: String ( label) , PreReleaseIdentifier :: Integer ( num) ) =
65- ( item, & pr[ i + 1 ] )
66- && label == "post"
67- && post. is_none ( )
68- {
69- post = Some ( * num) ;
70- extra_core. push ( Component :: VarField ( "post" . to_string ( ) ) ) ;
71- skip_next = true ;
72- continue ;
73- }
74-
75- // Check for keyword+number pattern
76- if i + 1 < pr. len ( )
77- && let ( PreReleaseIdentifier :: String ( label) , PreReleaseIdentifier :: Integer ( num) ) =
78- ( item, & pr[ i + 1 ] )
79- && let Some ( normalized_label) = normalize_pre_release_label ( label)
80- && pre_release. is_none ( )
81- {
82- pre_release = Some ( PreReleaseVar {
83- label : normalized_label,
84- number : Some ( * num) ,
85- } ) ;
86- extra_core. push ( Component :: VarField ( "pre_release" . to_string ( ) ) ) ;
87- skip_next = true ;
88- continue ;
89- }
90-
91- // Check for keyword-only pattern
92- if let PreReleaseIdentifier :: String ( label) = item
93- && let Some ( normalized_label) = normalize_pre_release_label ( label)
94- && pre_release. is_none ( )
95- {
96- pre_release = Some ( PreReleaseVar {
97- label : normalized_label,
98- number : None ,
99- } ) ;
100- extra_core. push ( Component :: VarField ( "pre_release" . to_string ( ) ) ) ;
101- continue ;
102- }
103-
104- // Regular component
105- extra_core. push ( match item {
106- PreReleaseIdentifier :: String ( s) => Component :: String ( s. clone ( ) ) ,
107- PreReleaseIdentifier :: Integer ( n) => Component :: Integer ( * n) ,
108- } ) ;
109- }
110-
111- ( pre_release, extra_core, epoch, post, dev)
112- } else {
113- ( None , Vec :: new ( ) , None , None , None )
114- } ;
129+ let ( pre_release, extra_core, epoch, post, dev) : ProcessResult = semver
130+ . pre_release
131+ . as_ref ( )
132+ . map ( |pr| PreReleaseProcessor :: new ( ) . process ( pr) )
133+ . unwrap_or_default ( ) ;
115134
116135 Zerv {
117136 schema : ZervSchema {
0 commit comments