@@ -10,6 +10,9 @@ use std::io::{stdout, BufRead, BufReader, BufWriter};
1010use std:: path:: PathBuf ;
1111use std:: { fs, io, process} ;
1212
13+ #[ cfg( feature = "cq" ) ]
14+ use jaq_all:: { jaq_core:: { Ctx , Vars , data:: JustLut } , jaq_std} ;
15+
1316#[ derive( Parser , Debug ) ]
1417#[ structopt( name = "cp2cp" , version = env!( "CARGO_PKG_VERSION" ) , author = env!( "CARGO_PKG_AUTHORS" ) , about = "ChainPack to Cpon and back utility" ) ]
1518struct Cli {
@@ -30,13 +33,18 @@ struct Cli {
3033 /// File to process
3134 #[ arg( value_name = "FILE" ) ]
3235 file : Option < PathBuf > ,
36+ /// Run cq with this filter.
37+ #[ cfg( feature = "cq" ) ]
38+ #[ arg( long = "cq" ) ]
39+ cq_filter : Option < String > ,
3340}
3441
3542const CODE_SUCCESS : i32 = 0 ;
3643const CODE_READ_ERROR : i32 = 1 ;
3744const CODE_NOT_ENOUGH_DATA : i32 = 2 ;
3845const CODE_WRITE_ERROR : i32 = 4 ;
39-
46+ #[ cfg( feature = "cq" ) ]
47+ const CODE_UNEXPECTED_ERROR : i32 = 5 ;
4048struct ChainPackRpcBlockResult {
4149 block_length : Option < usize > ,
4250 frame_length : Option < u64 > ,
@@ -138,7 +146,7 @@ fn main() {
138146 Some ( filename) => Box :: new ( BufReader :: new ( fs:: File :: open ( filename) . unwrap ( ) ) ) ,
139147 } ;
140148
141- let res = if opts. cpon_input {
149+ let read_result = if opts. cpon_input {
142150 let mut rd = CponReader :: new ( & mut reader) ;
143151 rd. read ( )
144152 } else if opts. chainpack_rpc_block {
@@ -147,31 +155,63 @@ fn main() {
147155 let mut rd = ChainPackReader :: new ( & mut reader) ;
148156 rd. read ( )
149157 } ;
150- let rv = match res {
158+
159+ let input_value = match read_result {
151160 Err ( e) => {
152161 eprintln ! ( "Parse input error: {:?}" , e) ;
153162 process:: exit ( CODE_READ_ERROR ) ;
154163 }
155164 Ok ( rv) => rv,
156165 } ;
157- let mut writer = BufWriter :: new ( stdout ( ) ) ;
158- let res = if opts. chainpack_output {
159- let mut wr = ChainPackWriter :: new ( & mut writer) ;
160- wr. write ( & rv)
166+
167+ #[ cfg( feature = "cq" ) ]
168+ let output_values = if let Some ( filter) = opts. cq_filter {
169+ let filter = match jaq_all:: compile_with ( & filter, jaq_std:: defs ( ) , jaq_std:: funs ( ) , & [ ] ) {
170+ Ok ( filter) => filter,
171+ Err ( error) => {
172+ eprintln ! ( "Failed to parse cq filter: {error:?}" ) ;
173+ process:: exit ( CODE_READ_ERROR ) ;
174+ } ,
175+ } ;
176+
177+ let ctx = Ctx :: < JustLut < shvproto:: RpcValue > > :: new ( & filter. lut , Vars :: new ( [ ] ) ) ;
178+ let outputs = filter. id . run ( ( ctx, input_value) ) ;
179+ outputs. filter_map ( |output|
180+ match output {
181+ Ok ( rv) => Some ( rv) ,
182+ Err ( err) => {
183+ eprintln ! ( "Unexpected error while processing the cq filter: {err:?}" ) ;
184+ process:: exit ( CODE_UNEXPECTED_ERROR )
185+ } ,
186+ } ) . collect :: < Vec < _ > > ( )
161187 } else {
162- let mut wr = CponWriter :: new ( & mut writer) ;
163- wr. set_no_oneliners ( opts. no_oneliners ) ;
164- if let Some ( s) = opts. indent {
165- if s == "\\ t" {
166- wr. set_indent ( "\t " . as_bytes ( ) ) ;
167- } else {
168- wr. set_indent ( s. as_bytes ( ) ) ;
169- }
170- }
171- wr. write ( & rv)
172- } ;
173- if let Err ( e) = res {
174- eprintln ! ( "Write output error: {:?}" , e) ;
175- process:: exit ( CODE_WRITE_ERROR ) ;
188+ vec ! [ input_value]
176189 } ;
190+
191+ #[ cfg( not( feature = "cq" ) ) ]
192+ let output_values = vec ! [ input_value] ;
193+
194+ let mut writer = BufWriter :: new ( stdout ( ) ) ;
195+ for output_value in output_values {
196+ let res = if opts. chainpack_output {
197+ let mut wr = ChainPackWriter :: new ( & mut writer) ;
198+ wr. write ( & output_value)
199+ } else {
200+ let mut wr = CponWriter :: new ( & mut writer) ;
201+ wr. set_no_oneliners ( opts. no_oneliners ) ;
202+ if let Some ( s) = & opts. indent {
203+ if s == "\\ t" {
204+ wr. set_indent ( "\t " . as_bytes ( ) ) ;
205+ } else {
206+ wr. set_indent ( s. as_bytes ( ) ) ;
207+ }
208+ }
209+ wr. write ( & output_value)
210+ } ;
211+
212+ if let Err ( e) = res {
213+ eprintln ! ( "Write output error: {:?}" , e) ;
214+ process:: exit ( CODE_WRITE_ERROR ) ;
215+ } ;
216+ }
177217}
0 commit comments