@@ -48,13 +48,14 @@ pub struct Command {
48
48
pub enum CommandKind {
49
49
Has ,
50
50
Count ,
51
+ Is ,
51
52
}
52
53
53
54
impl CommandKind {
54
55
fn validate ( & self , args : & [ String ] , command_num : usize , lineno : usize ) -> bool {
55
56
let count = match self {
56
57
CommandKind :: Has => ( 1 ..=3 ) . contains ( & args. len ( ) ) ,
57
- CommandKind :: Count => 3 == args. len ( ) ,
58
+ CommandKind :: Count | CommandKind :: Is => 3 == args. len ( ) ,
58
59
} ;
59
60
60
61
if !count {
@@ -83,6 +84,7 @@ impl fmt::Display for CommandKind {
83
84
let text = match self {
84
85
CommandKind :: Has => "has" ,
85
86
CommandKind :: Count => "count" ,
87
+ CommandKind :: Is => "is" ,
86
88
} ;
87
89
write ! ( f, "{}" , text)
88
90
}
@@ -127,6 +129,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
127
129
let cmd = match cmd {
128
130
"has" => CommandKind :: Has ,
129
131
"count" => CommandKind :: Count ,
132
+ "is" => CommandKind :: Is ,
130
133
_ => {
131
134
print_err ( & format ! ( "Unrecognized command name `@{}`" , cmd) , lineno) ;
132
135
errors = true ;
@@ -180,6 +183,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
180
183
/// Performs the actual work of ensuring a command passes. Generally assumes the command
181
184
/// is syntactically valid.
182
185
fn check_command ( command : Command , cache : & mut Cache ) -> Result < ( ) , CkError > {
186
+ // FIXME: Be more granular about why, (eg syntax error, count not equal)
183
187
let result = match command. kind {
184
188
CommandKind :: Has => {
185
189
match command. args . len ( ) {
@@ -220,6 +224,18 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
220
224
Err ( _) => false ,
221
225
}
222
226
}
227
+ CommandKind :: Is => {
228
+ // @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
229
+ assert_eq ! ( command. args. len( ) , 3 ) ;
230
+ let val = cache. get_value ( & command. args [ 0 ] ) ?;
231
+ match select ( & val, & command. args [ 1 ] ) {
232
+ Ok ( results) => {
233
+ let pat: Value = serde_json:: from_str ( & command. args [ 2 ] ) . unwrap ( ) ;
234
+ results. len ( ) == 1 && * results[ 0 ] == pat
235
+ }
236
+ Err ( _) => false ,
237
+ }
238
+ }
223
239
} ;
224
240
225
241
if result == command. negated {
0 commit comments