Skip to content

Commit 65c8de3

Browse files
authored
Merge pull request #3 from olback/docs
Docs
2 parents 5631fd6 + 1babfee commit 65c8de3

21 files changed

+772
-105
lines changed

Cargo.lock

Lines changed: 237 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ serde = "1.0.101"
1414
dirs = "2.0.2"
1515
toml = "0.5.3"
1616
rpassword = "4.0.1"
17+
zip = "0.5.3"
18+
crossbeam-channel = "0.3.8"
19+
# notify = {version = "5.0.0-pre.1", features = ["serde"] }
20+
notify = "5.0.0-pre.1"

LibraryLoader.example.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[settings]
2-
download_path = "download" # Path to download/save libs to. Paths can be absolute or relative. Relative paths are relative to the current working directory.
3-
# <not implemented> watch_path = "watch" # Path to watch for zipped .epw files.
4-
# <not implemented> format = "" # What format should be saved? Eagle, kikad, ..
2+
output_path = "download" # Path to download/save libs to. Paths can be absolute or relative. Relative paths are relative to the current working directory.
3+
# watch_path = "" # Path to watch for zipped .epw files.
4+
# format = "" # What format should be saved? Eagle, kikad, ..
55

66
# Component Search Engine Credentials
77
[profile]

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
# [WIP] Library Loader :books:
1+
# Library Loader :books:
22

3-
[![CircleCI](https://circleci.com/gh/olback/library-loader/tree/master.svg?style=svg)](https://circleci.com/gh/olback/library-loader/tree/master)
3+
![Screenshot](libloader.png)
4+
5+
OS/Platform | Status
6+
----------- | ------
7+
Linux x86_64 | [![CircleCI](https://circleci.com/gh/olback/library-loader/tree/master.svg?style=svg)](https://circleci.com/gh/olback/library-loader/tree/master)
8+
Windows | WIP
9+
Mac | WIP
410

511
Rust implementation of [https://www.samacsys.com/library-loader/](https://www.samacsys.com/library-loader/).
612

TODO.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
* [x] [Code] See `src/cse.rs#66`
66
* [x] [Code] Implement `std::fmt::Display` for `error::LLError`
77
* [ ] ~~[Feature] Mass download~~
8-
* [ ] [Feature] File watcher for zipped epw (and epw??) files
9-
* [ ] [Feature] Auto unzip folder and copy lib to libs folder
8+
* [x] [Feature] File watcher for zipped epw (and epw??) files
9+
* [x] [Feature] Auto unzip folder and copy lib to libs folder
1010
* [ ] [Code] New struct for CLI-only options
1111
* [x] [Feature] When using `-g`, treat input as output path
12+
* [ ] [Code] Split extractor from format
13+
* [ ] [Docs] Proper documentation
14+
* [ ] [Code] Document the code...
15+
* [ ] [Feature] Show Desktop Notification?
16+
* [ ] [Feature] Additional flag for `-g` to save in uses config dir.

cli.yml

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ author: "olback <libloader@olback.net>"
44
about: "Download libraries from componentsearchengine.com"
55
args:
66
- input:
7-
help: "Path to .eqw file"
7+
help: "Path to .eqw/.zip file"
88
# required: true
99
index: 1
1010
- id:
@@ -20,31 +20,57 @@ args:
2020
value_name: config
2121
takes_value: true
2222
multiple: false
23-
# - watch:
24-
# help: "Path to watch for .epw files. Setting this will enable watch-mode"
25-
# short: w
26-
# long: watch
27-
# value_name: watch
28-
# takes_value: true
29-
# multiple: false
23+
- watch:
24+
help: "Path to watch for .epw files. Setting this will enable watch-mode"
25+
short: w
26+
long: watch
27+
value_name: watch
28+
takes_value: true
29+
multiple: false
30+
conflicts_with:
31+
- id
32+
- generate
3033
- output:
3134
help: "Path to save output in"
3235
short: o
3336
long: output
3437
value_name: output
3538
takes_value: true
3639
multiple: false
37-
# Not implemented yet
38-
# - format:
39-
# help: "Specify which format to output"
40-
# short: f
41-
# long: format
42-
# value_name: format
43-
# takes_value: true
44-
# multiple: false
45-
# possible_values:
46-
# - eagle
47-
# # - kikad
40+
- format:
41+
help: "Specify which format to output"
42+
short: f
43+
long: format
44+
value_name: format
45+
takes_value: true
46+
multiple: false
47+
possible_values:
48+
# - 3d
49+
# - allegro
50+
# - altium
51+
# - cadstar
52+
# - capture
53+
# - circuitstudio
54+
# - cr_5000
55+
# - cr_8000
56+
# - dehdl
57+
# - designspark_pcb
58+
# - designspark_pcb_pro
59+
# - diptrace
60+
- eagle
61+
# - easyeda
62+
# - easy_pc
63+
# - ecadstar
64+
# - kicad
65+
# - orcad_allegro16
66+
# - pads
67+
# - proteus
68+
# - pulsonix
69+
# - solidworks_pcb
70+
# - target_3001
71+
# - xdx_designer
72+
# - xpedition
73+
- zip
4874
- generate:
4975
help: "Generate sample config"
5076
short: g

epw/ATMEGA328P-AU-pcb-part-libraries.epw

Lines changed: 0 additions & 9 deletions
This file was deleted.

libloader.png

71.1 KB
Loading

src/config.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::profile::Profile;
22
use super::consts::LL_CONFIG;
33
use super::error::{LLResult, LLError};
4+
use super::format::Format;
45
use serde::Deserialize;
56
use std::{fs, path::PathBuf};
67
use clap::{self, load_yaml, crate_version};
@@ -20,14 +21,14 @@ struct ParseSettings {
2021
format: Option<String> // If set, extract relevant files and place them in output_path
2122
}
2223

23-
#[derive(Debug)]
24+
#[derive(Debug, Clone)]
2425
pub struct Settings {
2526
pub output_path: String,
2627
pub watch_path: Option<String>,
27-
pub format: Option<String>
28+
pub format: Format
2829
}
2930

30-
#[derive(Debug)]
31+
#[derive(Debug, Clone)]
3132
pub struct Config {
3233
pub settings: Settings,
3334
pub profile: Profile,
@@ -64,8 +65,8 @@ impl Config {
6465
None => None
6566
},
6667
format: match s.format {
67-
Some(v) => Some(String::from(v)),
68-
None => None
68+
Some(v) => Format::from(v),
69+
None => Self::default().settings.format
6970
},
7071
}
7172
},
@@ -93,7 +94,7 @@ impl Config {
9394
None => settings.watch_path
9495
},
9596
format: match matches.value_of("format") {
96-
Some(v) => Some(String::from(v)),
97+
Some(v) => Format::from(v),
9798
None => settings.format
9899
}
99100
},
@@ -119,7 +120,7 @@ impl Config {
119120
None => Self::default().settings.watch_path
120121
},
121122
format: match matches.value_of("format") {
122-
Some(v) => Some(String::from(v)),
123+
Some(v) => Format::from(v),
123124
None => Self::default().settings.format
124125
},
125126
},
@@ -141,7 +142,6 @@ impl Config {
141142
{
142143
println!("-- Debug info from {file}#{line} --", file = std::file!(), line = std::line!());
143144
println!("{:#?}", conf);
144-
println!("-- End debug info from {file}#{line} --", file = std::file!(), line = std::line!());
145145
}
146146

147147
conf
@@ -179,22 +179,21 @@ impl Config {
179179

180180
match conf {
181181
Some(c) => Ok(c),
182-
None => Err(LLError::new(format!("{} not found", LL_CONFIG)))
182+
None => Err(LLError::new(format!("{file}#{line}: {p} not found", file = std::file!(), line = std::line!(), p = LL_CONFIG)))
183183
}
184184

185185
}
186186

187187
pub fn generate(input: &String) -> LLResult<String> {
188188

189-
// let path = PathBuf::from(LL_CONFIG);
190189
let path = PathBuf::from(match input.trim().is_empty() {
191190
true => LL_CONFIG,
192191
false => input
193192
});
194193

195194
if path.clone().exists() {
196195

197-
return Err(LLError::new(format!("{} already exists", path.to_str().unwrap())))
196+
return Err(LLError::new(format!("{file}#{line}: {err} already exists", file = std::file!(), line = std::line!(), err = path.to_str().unwrap())))
198197

199198
}
200199

@@ -203,7 +202,7 @@ impl Config {
203202
let path_as_string = String::from(path.to_str().unwrap());
204203
Ok(path_as_string)
205204
},
206-
Err(e) => Err(LLError::new(format!("{}", e)))
205+
Err(e) => Err(LLError::new(format!("{}#{}: {}", std::file!(), std::line!(), e)))
207206
}
208207

209208
}
@@ -220,7 +219,7 @@ impl Default for Config {
220219
settings: Settings {
221220
output_path: String::from("download"),
222221
watch_path: None,
223-
format: None
222+
format: Format::ZIP
224223
},
225224
profile: profile,
226225
input: String::new(),

src/cse.rs

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1-
use super::profile::Profile;
1+
use super::config::Config;
2+
use super::format::{self, Extractor, Format, Files};
23
use super::epw::Epw;
34
use super::error::{LLResult, LLError};
45
use super::cse_result::CSEResult;
5-
use reqwest::{self, header};
66
use super::consts::COMPONENT_SEARCH_ENGINE_URL;
7+
use std::{
8+
path::PathBuf,
9+
collections::HashMap
10+
};
11+
use reqwest::{self, header};
12+
use zip;
713

814
pub struct CSE {
9-
auth: String
15+
auth: String,
16+
config: Config
1017
}
1118

1219
impl CSE {
1320

14-
pub fn new(profile: &Profile) -> Self {
21+
pub fn new(config: &Config) -> Self {
1522
CSE {
16-
auth: profile.to_base64()
23+
auth: config.profile.to_base64(),
24+
config: config.clone()
1725
}
1826
}
1927

@@ -43,9 +51,7 @@ impl CSE {
4351

4452
let mut body = Vec::<u8>::new();
4553
if res.copy_to(&mut body).is_err() {
46-
4754
return Err(LLError::new("Error copying data from response"))
48-
4955
}
5056

5157
let filename = match res.headers().get("content-disposition") {
@@ -73,9 +79,53 @@ impl CSE {
7379
println!("-- End debug info from {file}#{line} --", file = std::file!(), line = std::line!());
7480
}
7581

82+
if &self.config.settings.format == &Format::ZIP {
83+
84+
let mut files: Files = HashMap::new();
85+
files.insert(filename, body);
86+
87+
Ok(CSEResult {
88+
output_path: self.config.settings.output_path.to_owned(),
89+
files: files
90+
})
91+
92+
} else {
93+
94+
let lib_name = match filename.starts_with("LIB_") {
95+
true => filename.as_str()[4..].replace(".zip", ""),
96+
false => filename.replace(".zip", "")
97+
};
98+
99+
self.unzip(lib_name, body)
100+
101+
}
102+
103+
}
104+
105+
fn unzip(&self, lib_name: String, data: Vec<u8>) -> LLResult<CSEResult> {
106+
107+
let reader = std::io::Cursor::new(&data);
108+
let mut archive = zip::ZipArchive::new(reader)?;
109+
let mut files: Files = HashMap::new();
110+
111+
for i in 0..archive.len() {
112+
113+
let mut item = archive.by_index(i)?;
114+
let filename = String::from(item.name());
115+
116+
match &self.config.settings.format {
117+
Format::EAGLE => format::eagle::Extractor::extract(&mut files, filename, &mut item)?,
118+
// ! NOTE: DO NOT ADD A _ => {} CATCHER HERE!
119+
Format::ZIP => return Err(LLError::new("This should be unreachable!"))
120+
};
121+
122+
}
123+
124+
let path = PathBuf::from(&self.config.settings.output_path).join(lib_name);
125+
76126
Ok(CSEResult {
77-
filename: filename,
78-
data: body
127+
output_path: path.to_string_lossy().to_string(),
128+
files: files
79129
})
80130

81131
}

0 commit comments

Comments
 (0)