@@ -52,15 +52,48 @@ impl InterruptState {
52
52
}
53
53
}
54
54
55
+ #[ derive( Debug , Clone , PartialEq , Eq , Default ) ]
56
+ struct CycleStateInner {
57
+ // The indices of all the cycles encountered during rendering.
58
+ cycles : HashMap < String , usize > ,
59
+ }
60
+
61
+ impl CycleStateInner {
62
+ fn cycle_index ( & mut self , name : & str , max : usize ) -> usize {
63
+ let i = self . cycles . entry ( name. to_owned ( ) ) . or_insert ( 0 ) ;
64
+ let j = * i;
65
+ * i = ( * i + 1 ) % max;
66
+ j
67
+ }
68
+ }
69
+
70
+ /// See `cycle` tag.
71
+ pub struct CycleState < ' a > {
72
+ context : & ' a mut Context ,
73
+ }
74
+
75
+ impl < ' a > CycleState < ' a > {
76
+ pub fn cycle_element ( & mut self , name : & str , values : & [ Argument ] ) -> Result < Value > {
77
+ let index = self . context . cycles . cycle_index ( name, values. len ( ) ) ;
78
+ if index >= values. len ( ) {
79
+ return Err ( Error :: with_msg (
80
+ "cycle index out of bounds, most likely from mismatched cycles" ,
81
+ ) . context ( "index" , & index)
82
+ . context ( "count" , & values. len ( ) ) ) ;
83
+ }
84
+
85
+ let val = values[ index] . evaluate ( self . context ) ?;
86
+ Ok ( val)
87
+ }
88
+ }
89
+
55
90
#[ derive( Default ) ]
56
91
pub struct Context {
57
92
stack : Vec < Object > ,
58
93
globals : Object ,
59
94
60
95
interrupt : InterruptState ,
61
-
62
- /// The indices of all the cycles encountered during rendering.
63
- cycles : HashMap < String , usize > ,
96
+ cycles : CycleStateInner ,
64
97
65
98
filters : sync:: Arc < HashMap < & ' static str , BoxedValueFilter > > ,
66
99
}
@@ -81,24 +114,6 @@ impl Context {
81
114
self
82
115
}
83
116
84
- pub fn cycle_element ( & mut self , name : & str , values : & [ Argument ] ) -> Result < Option < Value > > {
85
- let index = {
86
- let i = self . cycles . entry ( name. to_owned ( ) ) . or_insert ( 0 ) ;
87
- let j = * i;
88
- * i = ( * i + 1 ) % values. len ( ) ;
89
- j
90
- } ;
91
-
92
- if index >= values. len ( ) {
93
- return Err ( Error :: with_msg ( "cycle index out of bounds" )
94
- . context ( "index" , & index)
95
- . context ( "count" , & values. len ( ) ) ) ;
96
- }
97
-
98
- let val = values[ index] . evaluate ( self ) ?;
99
- Ok ( Some ( val) )
100
- }
101
-
102
117
pub fn get_filter < ' b > ( & ' b self , name : & str ) -> Option < & ' b FilterValue > {
103
118
self . filters . get ( name) . map ( |f| {
104
119
let f: & FilterValue = f;
@@ -114,6 +129,12 @@ impl Context {
114
129
& mut self . interrupt
115
130
}
116
131
132
+ pub fn cycles < ' a > ( & ' a mut self ) -> CycleState < ' a > {
133
+ CycleState {
134
+ context : self ,
135
+ }
136
+ }
137
+
117
138
/// Creates a new variable scope chained to a parent scope.
118
139
fn push_scope ( & mut self ) {
119
140
self . stack . push ( Object :: new ( ) ) ;
0 commit comments