From 88608034740bddb9cc11462d0e4b2cbe5fa69e88 Mon Sep 17 00:00:00 2001 From: Sam Mason Date: Thu, 5 Nov 2020 14:12:00 +1100 Subject: [PATCH] Changes --- ll-core/src/cse.rs | 28 ++++- ll-core/src/cse_result.rs | 21 ++-- ll-core/src/format/mod.rs | 32 +++++- ll-core/src/format/processors/d3.rs | 7 ++ ll-core/src/format/processors/eagle.rs | 7 ++ ll-core/src/format/processors/easyeda.rs | 7 ++ ll-core/src/format/processors/kicad.rs | 130 +++++++++++++++++++++++ ll-core/src/format/processors/mod.rs | 27 +++++ ll-core/src/watcher.rs | 6 +- 9 files changed, 247 insertions(+), 18 deletions(-) create mode 100644 ll-core/src/format/processors/d3.rs create mode 100644 ll-core/src/format/processors/eagle.rs create mode 100644 ll-core/src/format/processors/easyeda.rs create mode 100644 ll-core/src/format/processors/kicad.rs create mode 100644 ll-core/src/format/processors/mod.rs diff --git a/ll-core/src/cse.rs b/ll-core/src/cse.rs index 9f9cf4e..e745eee 100644 --- a/ll-core/src/cse.rs +++ b/ll-core/src/cse.rs @@ -2,11 +2,13 @@ use super::{ config::Config, format::{ Files, - ECAD + ECAD, + Output }, epw::Epw, error::LLResult, cse_result::CSEResult, + cse_result::CSEUnprocessedResult, consts::COMPONENT_SEARCH_ENGINE_URL, new_err }; @@ -104,13 +106,13 @@ impl CSE { false => filename.replace(".zip", "") }; - self.unzip(lib_name, body) - + let mut v = self.unzip(lib_name, body)?; + self.process(&mut v) } } - fn unzip(&self, lib_name: String, data: Vec) -> LLResult { + fn unzip(&self, lib_name: String, data: Vec) -> LLResult { let reader = std::io::Cursor::new(&data); let mut archive = zip::ZipArchive::new(reader)?; @@ -130,11 +132,27 @@ impl CSE { false => PathBuf::from(&self.config.settings.output_path) }; - Ok(CSEResult { + Ok(CSEUnprocessedResult { output_path: path.to_string_lossy().to_string(), files: files }) } + fn process(&self,rawres : &mut CSEUnprocessedResult) -> LLResult + { + let mut output_files = Files::new(); + + for (filename, mut file) in rawres.files.iter_mut() + { + self.config.settings.format.process(rawres.output_path.clone(), &mut output_files, filename.clone(), &mut file)?; + } + + Ok(CSEResult + { + output_path : rawres.output_path.clone(), + files : output_files, + }) + } + } diff --git a/ll-core/src/cse_result.rs b/ll-core/src/cse_result.rs index b4e5c89..e9c27b6 100644 --- a/ll-core/src/cse_result.rs +++ b/ll-core/src/cse_result.rs @@ -15,6 +15,12 @@ use std::{ // pub data: Vec // } +pub struct CSEUnprocessedResult +{ + pub output_path: String, + pub files: HashMap> +} + pub struct CSEResult { pub output_path: String, pub files: HashMap> @@ -28,12 +34,15 @@ impl CSEResult { if &self.files.len() > &0 { - if !save_dir.exists() { - fs::create_dir_all(save_dir)?; - } - for (filename, data) in &self.files { let path = save_dir.join(filename); + let dir = path.parent().unwrap(); + + if !dir.exists() + { + fs::create_dir_all(dir)?; + } + Self::write(path, data.to_vec())?; } @@ -51,10 +60,6 @@ impl CSEResult { let p = path.to_str().unwrap().to_string(); - if path.exists() { - return Err(new_err!(format!("{} already exists!", p))); - } - match fs::write(&path, &data) { Ok(_) => Ok(p), Err(e) => Err(new_err!(e)) diff --git a/ll-core/src/format/mod.rs b/ll-core/src/format/mod.rs index 1774fae..d46301f 100644 --- a/ll-core/src/format/mod.rs +++ b/ll-core/src/format/mod.rs @@ -1,4 +1,5 @@ mod extractors; +mod processors; use zip::read::ZipFile; use super::error::LLResult; @@ -14,12 +15,20 @@ pub enum ECAD { ZIP } +#[derive(PartialEq,Debug, Clone)] +pub enum Output +{ + File(&'static str), + Folder(&'static str) +} + #[derive(Debug, Clone, PartialEq)] pub struct Format { pub name: String, pub ecad: ECAD, pub create_folder: bool, match_path: Vec<&'static str>, + output : Vec, ignore: Vec<&'static str> } @@ -35,7 +44,8 @@ impl Format { name: f, ecad: ECAD::D3, create_folder: true, - match_path: "3D", + match_path: vec!["3D"], + output: vec![], ignore: vec![] }, "eagle" => Self { @@ -43,6 +53,7 @@ impl Format { ecad: ECAD::EAGLE, create_folder: false, match_path: vec!["EAGLE/", "/3D/"], + output: vec![], ignore: vec!["Readme.html"] }, "easyeda" => Self { @@ -50,13 +61,15 @@ impl Format { ecad: ECAD::EASYEDA, create_folder: false, match_path: vec!["EasyEDA/", "/3D/"], + output: vec![], ignore: vec!["Readme.html"] }, "kicad" => Self { name: f, ecad: ECAD::KICAD, - create_folder: true, + create_folder: false, match_path: vec!["KiCad/", "/3D/"], + output: vec![Output::File("LibraryLoader.lib"), Output::File("LibraryLoader.dcm"), Output::Folder("LibraryLoader.pretty")], ignore: vec![] }, "zip" => Self { @@ -64,6 +77,7 @@ impl Format { ecad: ECAD::ZIP, create_folder: false, match_path: vec![""], + output: vec![], ignore: vec![] }, _ => { @@ -90,4 +104,18 @@ impl Format { Ok(()) } + pub fn process(&self, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec) -> LLResult<()> + { + match &self.ecad { + // * Keep these in alphabetical order + ECAD::D3 => processors::d3::process(&self, output_path, output_files, file_path, item)?, + ECAD::EAGLE => processors::eagle::process(&self, output_path, output_files, file_path, item)?, + ECAD::EASYEDA => processors::easyeda::process(&self, output_path, output_files, file_path, item)?, + ECAD::KICAD => processors::kicad::process(&self, output_path, output_files, file_path, item)?, + ECAD::ZIP => unreachable!("ZIP not handled!") + // ! NOTE: DO NOT ADD A _ => {} CATCHER HERE! + }; + + Ok(()) + } } diff --git a/ll-core/src/format/processors/d3.rs b/ll-core/src/format/processors/d3.rs new file mode 100644 index 0000000..3a1e288 --- /dev/null +++ b/ll-core/src/format/processors/d3.rs @@ -0,0 +1,7 @@ +use super::*; + +pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec) -> LLResult<()> { + + generic_processor(format, output_path, output_files, file_path, item) + +} diff --git a/ll-core/src/format/processors/eagle.rs b/ll-core/src/format/processors/eagle.rs new file mode 100644 index 0000000..3a1e288 --- /dev/null +++ b/ll-core/src/format/processors/eagle.rs @@ -0,0 +1,7 @@ +use super::*; + +pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec) -> LLResult<()> { + + generic_processor(format, output_path, output_files, file_path, item) + +} diff --git a/ll-core/src/format/processors/easyeda.rs b/ll-core/src/format/processors/easyeda.rs new file mode 100644 index 0000000..3a1e288 --- /dev/null +++ b/ll-core/src/format/processors/easyeda.rs @@ -0,0 +1,7 @@ +use super::*; + +pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec) -> LLResult<()> { + + generic_processor(format, output_path, output_files, file_path, item) + +} diff --git a/ll-core/src/format/processors/kicad.rs b/ll-core/src/format/processors/kicad.rs new file mode 100644 index 0000000..b320ca2 --- /dev/null +++ b/ll-core/src/format/processors/kicad.rs @@ -0,0 +1,130 @@ +use super::*; + +const LIBRARY : &str = "LibraryLoader.lib"; +const DOCLIB : &str = "LibraryLoader.dcm"; +const FP_FOLDER : &str = "LibraryLoader.pretty"; +const U3D_FOLDER : &str = "LibraryLoader-3dmodels"; + +pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_name : String, item : &mut Vec) -> LLResult<()> { + + let file_path = PathBuf::from(output_path.clone()).join(file_name.clone()); + if let Some(ext) = &file_path.extension() + { + match ext.to_str() + { + Some("kicad_mod") => + { + output_files.insert(format!("{}/{}", FP_FOLDER, file_name), item.clone()); + }, + Some("lib") => + { + let chars = match std::str::from_utf8(&item[..]) + { + Ok(v) => v, + Err(e) => return Err( + LLError::new(format!("Could not convert file to valid utf8: {} ({})", e, file_name), "ll-core/src/format/processors/kicad.rs", 24) + ) + }; + + let mut d_out = Vec::new(); + + let enddefs : Vec<_> = chars.match_indices("ENDDEF").collect(); + let mut start = 0; + for (idx,_) in enddefs + { + let matching_def = chars[start..idx].match_indices("DEF").collect::>()[0].0; + d_out.extend_from_slice(&chars[matching_def..idx+6].as_bytes()); + start = idx+7; + } + + if let Some(f) = output_files.get_mut(LIBRARY) { + f.append(&mut d_out); + } + else { + // Create entry in output_files for library + let mut file_data = Vec::new(); + + // Load in from possibly existing file + let fn_lib = PathBuf::from(output_path).join(LIBRARY); + + if fn_lib.exists() + { + let mut f_lib = std::fs::File::open(fn_lib)?; + + f_lib.read_to_end(&mut file_data)?; + } + else { + file_data.extend_from_slice(b"EESchema-LIBRARY Version 2.3\n#encoding utf-8"); + } + file_data.push(b'\n'); + file_data.append(&mut d_out); + + output_files.insert(LIBRARY.to_string(), file_data); + } + }, + Some("dcm") => + { + let chars = match std::str::from_utf8(&item[..]) + { + Ok(v) => v, + Err(e) => return Err( + LLError::new(format!("Could not convert file to valid utf8: {} ({})", e, file_name), "ll-core/src/format/processors/kicad.rs", 68) + ) + }; + + let mut d_out = Vec::new(); + + let endcmps : Vec<_> = chars.match_indices("$ENDCMP").collect(); + let mut start = 0; + for (idx,_) in endcmps + { + let matching_cmp = chars[start..idx].match_indices("$CMP").collect::>()[0].0; + d_out.extend_from_slice(&chars[matching_cmp..idx+7].as_bytes()); + d_out.push(b'\n'); + start = idx+8; + } + + if let Some(f) = output_files.get_mut(DOCLIB) { + f.append(&mut d_out); + } + else { + // Create entry in output_files for library + let mut file_data = Vec::new(); + + // Load in from possibly existing file + let fn_lib = PathBuf::from(output_path).join(DOCLIB); + + if fn_lib.exists() + { + let mut f_lib = std::fs::File::open(fn_lib)?; + + f_lib.read_to_end(&mut file_data)?; + } + else { + file_data.extend_from_slice(b"EESchema-DOCLIB Version 2.0\n"); + } + + file_data.append(&mut d_out); + + output_files.insert(DOCLIB.to_string(), file_data); + } + }, + Some("stl") | Some("stp") | Some("wrl") => + { + // 3D Files + let mut folder = PathBuf::from(file_name.clone()); + folder.set_extension("3dshapes"); + output_files.insert(format!("{}/{}/{}",U3D_FOLDER,folder.to_string_lossy(), file_name), item.clone()); + }, + Some("mod") => + { + //Obsolete footprint module file + } + _ => println!("Unknown file type: {}", file_name) + } + } + + Ok(()) + /*generic_processor(format, output_path, output_files, file_name, item)*/ +} + diff --git a/ll-core/src/format/processors/mod.rs b/ll-core/src/format/processors/mod.rs new file mode 100644 index 0000000..1a5d98c --- /dev/null +++ b/ll-core/src/format/processors/mod.rs @@ -0,0 +1,27 @@ +// * Keep these in alphabetical order +pub mod eagle; +pub mod easyeda; +pub mod kicad; +pub mod d3; + +use std::collections::HashMap; + +pub(super) use zip::read::ZipFile; +pub(super) use std::{ + io::Read, + path::PathBuf +}; +pub(super) use super::{ + Format, + super::LLResult, + super::LLError +}; + +pub type Files = HashMap::>; + +pub(super) fn generic_processor(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec) -> LLResult<()> { + + output_files.insert(file_path, item.clone()); + + Ok(()) +} diff --git a/ll-core/src/watcher.rs b/ll-core/src/watcher.rs index 933ccd0..8e0004c 100644 --- a/ll-core/src/watcher.rs +++ b/ll-core/src/watcher.rs @@ -9,6 +9,7 @@ use std::{ path::PathBuf }; use super::{ + error::LLError, error::LLResult, cse::CSE, epw::Epw, @@ -183,7 +184,6 @@ impl Watcher { _ => {} }; - } fn handle_file(&self, path: &PathBuf) -> LLResult { @@ -194,10 +194,10 @@ impl Watcher { let res = &self.cse.get(epw)?; res.save() } else { - Err(LLError::new(format!("=> Ignoring non-zip: {}", path.to_str().unwrap()))) + Err(LLError::new(format!("=> Ignoring non-zip: {}", path.to_str().unwrap()), "ll-gui/watcher.rs", 198)) } None => { - Err(LLError::new(format!("=> Ignoring: {}", path.to_str().unwrap()))) + Err(LLError::new(format!("=> Ignoring: {}", path.to_str().unwrap()), "ll-gui/watcher.rs", 201)) } } }