Skip to content

Kicad integration #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions ll-core/src/cse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down Expand Up @@ -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<u8>) -> LLResult<CSEResult> {
fn unzip(&self, lib_name: String, data: Vec<u8>) -> LLResult<CSEUnprocessedResult> {

let reader = std::io::Cursor::new(&data);
let mut archive = zip::ZipArchive::new(reader)?;
Expand All @@ -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<CSEResult>
{
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,
})
}

}
21 changes: 13 additions & 8 deletions ll-core/src/cse_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ use std::{
// pub data: Vec<u8>
// }

pub struct CSEUnprocessedResult
{
pub output_path: String,
pub files: HashMap<String, Vec<u8>>
}

pub struct CSEResult {
pub output_path: String,
pub files: HashMap<String, Vec<u8>>
Expand All @@ -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())?;
}

Expand All @@ -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))
Expand Down
16 changes: 8 additions & 8 deletions ll-core/src/format/extractors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ pub(super) fn generic_extractor(format: &Format, files: &mut Files, file_path: S

}

if file_path_lower.contains(&format.match_path.to_lowercase()) {

let path = PathBuf::from(file_path);
let base_name = path.file_name().unwrap().to_string_lossy().to_string();
let mut f_data = Vec::<u8>::new();
item.read_to_end(&mut f_data)?;
files.insert(base_name, f_data);

let path = PathBuf::from(file_path);
for paths_to_extract in &format.match_path {
if file_path_lower.contains(paths_to_extract.to_lowercase().as_str()) {
let base_name = path.file_name().unwrap().to_string_lossy().to_string();
let mut f_data = Vec::<u8>::new();
item.read_to_end(&mut f_data)?;
files.insert(base_name, f_data);
}
}

Ok(())
Expand Down
42 changes: 35 additions & 7 deletions ll-core/src/format/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod extractors;
mod processors;
use zip::read::ZipFile;
use super::error::LLResult;

Expand All @@ -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: &'static str,
match_path: Vec<&'static str>,
output : Vec<Output>,
ignore: Vec<&'static str>
}

Expand All @@ -35,35 +44,40 @@ impl Format {
name: f,
ecad: ECAD::D3,
create_folder: true,
match_path: "3D",
match_path: vec!["3D"],
output: vec![],
ignore: vec![]
},
"eagle" => Self {
name: f,
ecad: ECAD::EAGLE,
create_folder: false,
match_path: "EAGLE",
match_path: vec!["EAGLE/", "/3D/"],
output: vec![],
ignore: vec!["Readme.html"]
},
"easyeda" => Self {
name: f,
ecad: ECAD::EASYEDA,
create_folder: false,
match_path: "EasyEDA",
match_path: vec!["EasyEDA/", "/3D/"],
output: vec![],
ignore: vec!["Readme.html"]
},
"kicad" => Self {
name: f,
ecad: ECAD::KICAD,
create_folder: true,
match_path: "KiCad",
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 {
name: f,
ecad: ECAD::ZIP,
create_folder: false,
match_path: "",
match_path: vec![""],
output: vec![],
ignore: vec![]
},
_ => {
Expand All @@ -90,4 +104,18 @@ impl Format {
Ok(())
}

pub fn process(&self, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec<u8>) -> 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(())
}
}
7 changes: 7 additions & 0 deletions ll-core/src/format/processors/d3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use super::*;

pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec<u8>) -> LLResult<()> {

generic_processor(format, output_path, output_files, file_path, item)

}
7 changes: 7 additions & 0 deletions ll-core/src/format/processors/eagle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use super::*;

pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec<u8>) -> LLResult<()> {

generic_processor(format, output_path, output_files, file_path, item)

}
7 changes: 7 additions & 0 deletions ll-core/src/format/processors/easyeda.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use super::*;

pub fn process(format: &Format, output_path : String, output_files : &mut Files, file_path : String, item : &mut Vec<u8>) -> LLResult<()> {

generic_processor(format, output_path, output_files, file_path, item)

}
130 changes: 130 additions & 0 deletions ll-core/src/format/processors/kicad.rs
Original file line number Diff line number Diff line change
@@ -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<u8>) -> 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::<Vec<_>>()[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::<Vec<_>>()[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)*/
}

Loading