| 
					
				 | 
			
			
				@@ -6,11 +6,11 @@ use std::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use binrw::{BinRead, BinWrite, BinWriterExt}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use clap::Parser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use clap::{Args, Parser, Subcommand}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use clap_verbosity_flag::{InfoLevel, Verbosity}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use diff::Diff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use env_logger::Target; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use ezcad::file::EzCadHeader; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use ezcad::{file::EzCadHeader, layer::Layer, objects::Object}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use log::{info, trace, warn}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use crate::config::{Config, Operations}; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -19,36 +19,58 @@ mod config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Debug, Parser)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct Cli { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Input file to parse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[command(subcommand)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    command: SubCommands, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Input .mlp file to parse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     input: PathBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// File to diff input against 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    diff: Option<PathBuf>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[command(flatten)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    verbose: Verbosity<InfoLevel>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Output file to write to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    output: Option<PathBuf>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Debug, Subcommand)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+enum SubCommands { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Diff(DiffCmd), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Query(QueryCmd), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Apply(ApplyConfig), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Configuration file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// Diff two .mlp files and print differences between the two 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Debug, Args)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct DiffCmd { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// File to diff input against 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    config: Option<PathBuf>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diff_file: PathBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// Queries input .mlp file for pen or object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Debug, Args)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct QueryCmd { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Print pen info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pen: Option<Vec<usize>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // /// Layer of object to print info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // #[arg(short = 'l', long, requires = "object")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // object_layer: Option<usize>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Print object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    object: Option<usize>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // /// Print object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // #[arg(short = 'b', long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // object: Option<usize>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Object layer to query object on 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short = 'b', long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    object_layer: Option<usize>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #[command(flatten)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    verbose: Verbosity<InfoLevel>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// Applies configuration YAML to input .mlp file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Debug, Args)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct ApplyConfig { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Configuration file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    config: PathBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Output file to write to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    output: Option<PathBuf>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fn main() { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -89,121 +111,127 @@ fn main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         warn!("Re-encoded input file does not match original file!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Print info on pens with non-default settings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (index, pen) in file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .filter(|x| *x.use_default == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .enumerate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        trace!("Pen {}: {:#?}", index, pen); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Print all objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (layer_index, layer) in file.layers_offset.iter().enumerate() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (object_index, object) in layer.objects.iter().enumerate() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            trace!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "Layer {}, Object {}: {:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                layer_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                object_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                object 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    match cli.command { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        SubCommands::Diff(args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "Processing diff file '{}'", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                args.diff_file.to_string_lossy() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut diff: File = File::open(args.diff_file).expect("Failed to open diff file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let diff_file: EzCadHeader = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                EzCadHeader::read_le(&mut diff).expect("Failed to parse diff file as EZCAD format"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Process pen query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cli.pen.map(|index| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for pen in index { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Diff pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "Pen #{}: {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                pen, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "{:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 file.pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    .get(pen) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    .expect("Invalid pen index") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .diff(&diff_file.pens_offset.data.pens) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Diff objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "{:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                file.layers_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .diff(&diff_file.layers_offset.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Process object query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // cli.object.map(|obj_index| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     let layer_index: usize = cli.object_layer.unwrap_or(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     let layer: &Layer = file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         .layers_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         .get(layer_index) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         .expect("Invalid layer index"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     let object: &Object = layer.objects.get(obj_index).expect("Invalid object index"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     info!("Layer {}, Object {}: {:?}", layer_index, obj_index, object); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     let pen_index: u32 = object.get_pen(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     trace!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         "Pen #{}: {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         pen_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //         file.pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //             .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //             .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //             .get(pen_index as usize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //             .expect("Invalid pen index in object") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //     // TODO: object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Process diff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cli.diff.map(|diff| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info!("Processing diff file '{}'", diff.to_string_lossy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let mut diff: File = File::open(diff).expect("Failed to open diff file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let diff_file: EzCadHeader = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            EzCadHeader::read_le(&mut diff).expect("Failed to parse diff file as EZCAD format"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Diff pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "{:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            file.pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        SubCommands::Query(args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Print info on pens with non-default settings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for (index, pen) in file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .diff(&diff_file.pens_offset.data.pens) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Diff objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "{:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            file.layers_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .diff(&diff_file.layers_offset.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Process config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cli.config.map(|config| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info!("Processing config file '{}'", config.to_string_lossy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let config: String = std::fs::read_to_string(config).expect("Failed to open config file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let config: Config = serde_yaml::from_str(&config).expect("Failed to parse config file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Patch pen settings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let time: Instant = Instant::now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .ops 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .apply(&mut file.pens_offset.data.pens, &mut file.layers_offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        trace!("Config processing time: {:?}", time.elapsed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Process output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cli.output.map(|output| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info!("Writing output file '{}'", output.to_string_lossy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Serialize to memory buffer for perf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let time: Instant = Instant::now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .write_le(&file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .expect("Failed to serialize contents as EZCAD format"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        trace!("Output file encode time: {:?}", time.elapsed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Write buffer to output file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let mut output: File = File::create(output).expect("Failed to open output file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .write_all(buffer.into_inner().as_slice()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .expect("Failed to write to output file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(|x| *x.use_default == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .enumerate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trace!("Pen {}: {:#?}", index, pen); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Print all objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for (layer_index, layer) in file.layers_offset.iter().enumerate() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for (object_index, object) in layer.objects.iter().enumerate() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    trace!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        "Layer {}, Object {}: {:#?}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        layer_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        object_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        object 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Process pen query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            args.pen.map(|pens| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for pen in pens { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        "Pen #{}: {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        pen, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        file.pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .get(pen) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .expect("Invalid pen index") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Process object query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            args.object.map(|obj_index| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let layer_index: usize = args.object_layer.unwrap_or(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let layer: &Layer = file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .layers_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .get(layer_index) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .expect("Invalid layer index"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let object: &Object = layer.objects.get(obj_index).expect("Invalid object index"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                info!("Layer {}, Object {}: {:?}", layer_index, obj_index, object); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let pen_index: u32 = *object.core().pen; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trace!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    "Pen #{}: {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    pen_index, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    file.pens_offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .get(pen_index as usize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .expect("Invalid pen index in object") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // TODO: object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        SubCommands::Apply(args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Process config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            info!("Processing config file '{}'", args.config.to_string_lossy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let config: String = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                std::fs::read_to_string(args.config).expect("Failed to open config file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let config: Config = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                serde_yaml::from_str(&config).expect("Failed to parse config file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Patch pen settings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let time: Instant = Instant::now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .ops 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .apply(&mut file.pens_offset.data.pens, &mut file.layers_offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            trace!("Config processing time: {:?}", time.elapsed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Process output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            args.output.map(|output| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                info!("Writing output file '{}'", output.to_string_lossy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Serialize to memory buffer for perf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let time: Instant = Instant::now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .write_le(&file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .expect("Failed to serialize contents as EZCAD format"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trace!("Output file encode time: {:?}", time.elapsed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Write buffer to output file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let mut output: File = File::create(output).expect("Failed to open output file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .write_all(buffer.into_inner().as_slice()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .expect("Failed to write to output file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |