main.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. use std::{
  2. fs::File,
  3. io::{Cursor, Read, Write},
  4. path::PathBuf,
  5. time::Instant,
  6. };
  7. use binrw::{BinRead, BinWrite, BinWriterExt};
  8. use clap::Parser;
  9. use clap_verbosity_flag::{InfoLevel, Verbosity};
  10. use diff::Diff;
  11. use env_logger::Target;
  12. use ezcad::file::EzCadHeader;
  13. use log::{info, trace, warn};
  14. use crate::config::{Config, Operations};
  15. mod config;
  16. #[derive(Debug, Parser)]
  17. struct Cli {
  18. /// Input file to parse
  19. #[arg(short, long)]
  20. input: PathBuf,
  21. /// File to diff input against
  22. #[arg(short, long)]
  23. diff: Option<PathBuf>,
  24. /// Output file to write to
  25. #[arg(short, long)]
  26. output: Option<PathBuf>,
  27. /// Configuration file
  28. #[arg(short, long)]
  29. config: Option<PathBuf>,
  30. #[command(flatten)]
  31. verbose: Verbosity<InfoLevel>,
  32. }
  33. fn main() {
  34. let cli: Cli = Cli::parse();
  35. env_logger::builder()
  36. .format_timestamp(None)
  37. .format_target(false)
  38. .filter_level(cli.verbose.log_level_filter())
  39. .target(Target::Stdout)
  40. .init();
  41. info!("Reading input file '{}'", cli.input.to_string_lossy());
  42. let mut input: File = File::open(cli.input).expect("Failed to open input file");
  43. // Deserialize to memory buffer for perf
  44. let mut input_file: Cursor<Vec<u8>> = Cursor::new(vec![]);
  45. input
  46. .read_to_end(input_file.get_mut())
  47. .expect("Failed to read input file");
  48. // Deserialize as EZCAD format
  49. let time: Instant = Instant::now();
  50. let mut file: EzCadHeader =
  51. EzCadHeader::read_le(&mut input_file).expect("Failed to parse input file as EZCAD format");
  52. trace!("Input file decode time: {:?}", time.elapsed());
  53. // Sanity check that re-encoded input file matches original
  54. info!("Validating re-encoding of input file");
  55. let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
  56. let time: Instant = Instant::now();
  57. file.write_le(&mut buffer)
  58. .expect("Failed to reserialize input file as EZCAD format");
  59. trace!("Input file re-encode time: {:?}", time.elapsed());
  60. if buffer.into_inner().as_slice().ne(input_file.get_ref()) {
  61. warn!("Re-encoded input file does not match original file!");
  62. }
  63. // Print info on pens with non-default settings
  64. for (index, pen) in file
  65. .pens_offset
  66. .data
  67. .pens
  68. .iter()
  69. .filter(|x| *x.use_default == 0)
  70. .enumerate()
  71. {
  72. trace!("Pen {}: {:#?}", index, pen);
  73. }
  74. // Print all objects
  75. for (layer_index, layer) in file.layers_offset.iter().enumerate() {
  76. for (object_index, object) in layer.objects.iter().enumerate() {
  77. trace!(
  78. "Layer {}, Object {}: {:#?}",
  79. layer_index,
  80. object_index,
  81. object
  82. );
  83. }
  84. }
  85. // Process diff
  86. cli.diff.map(|diff| {
  87. info!("Processing diff file '{}'", diff.to_string_lossy());
  88. let mut diff: File = File::open(diff).expect("Failed to open diff file");
  89. let diff_file: EzCadHeader =
  90. EzCadHeader::read_le(&mut diff).expect("Failed to parse diff file as EZCAD format");
  91. // Diff pens
  92. info!(
  93. "{:#?}",
  94. file.pens_offset
  95. .data
  96. .pens
  97. .diff(&diff_file.pens_offset.data.pens)
  98. );
  99. // Diff objects
  100. info!(
  101. "{:#?}",
  102. file.layers_offset
  103. .value
  104. .diff(&diff_file.layers_offset.value)
  105. );
  106. });
  107. // Process config
  108. cli.config.map(|config| {
  109. info!("Processing config file '{}'", config.to_string_lossy());
  110. let config: String = std::fs::read_to_string(config).expect("Failed to open config file");
  111. let config: Config = serde_yaml::from_str(&config).expect("Failed to parse config file");
  112. // Patch pen settings
  113. let time: Instant = Instant::now();
  114. config
  115. .ops
  116. .apply(&mut file.pens_offset.data.pens, &mut file.layers_offset);
  117. trace!("Config processing time: {:?}", time.elapsed());
  118. });
  119. // Process output
  120. cli.output.map(|output| {
  121. info!("Writing output file '{}'", output.to_string_lossy());
  122. // Serialize to memory buffer for perf
  123. let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
  124. let time: Instant = Instant::now();
  125. buffer
  126. .write_le(&file)
  127. .expect("Failed to serialize contents as EZCAD format");
  128. trace!("Output file encode time: {:?}", time.elapsed());
  129. // Write buffer to output file
  130. let mut output: File = File::create(output).expect("Failed to open output file");
  131. output
  132. .write_all(buffer.into_inner().as_slice())
  133. .expect("Failed to write to output file");
  134. });
  135. }