368 lines
12 KiB
Rust
368 lines
12 KiB
Rust
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Work {
|
|
name: String,
|
|
position: String,
|
|
start_date: String,
|
|
end_date: Option<String>,
|
|
logo: Logo,
|
|
description: String,
|
|
highlights: Vec<String>,
|
|
technologies: Vec<String>,
|
|
link: Option<Link>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Project {
|
|
name: String,
|
|
description: String,
|
|
start_date: String,
|
|
end_date: Option<String>,
|
|
presentation: Vec<String>,
|
|
highlights: Vec<String>,
|
|
keywords: Vec<String>,
|
|
link: Option<Link>,
|
|
logo: Option<Logo>,
|
|
image: Option<Image>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Image {
|
|
file: String,
|
|
// TODO: use enum directly instead of string
|
|
// position: ImagePosition,
|
|
position: String,
|
|
}
|
|
|
|
// #[derive(Debug, Deserialize)]
|
|
// TODO: possible implementation: https://www.reddit.com/r/rust/comments/10bab4v/serdejson_how_to_deserialize_and_serialize_an/
|
|
// enum ImagePosition {
|
|
// Left,
|
|
// Right,
|
|
// }
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Link {
|
|
uri: String,
|
|
label: String,
|
|
not_available: bool,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Logo {
|
|
file: String,
|
|
transparent_background: bool,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Education {
|
|
institution: String,
|
|
study_type: String,
|
|
area: String,
|
|
start_date: String,
|
|
end_date: Option<String>,
|
|
logo: Option<Logo>,
|
|
courses: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Wallpaper {
|
|
filename: String,
|
|
date: String,
|
|
gps: Gps,
|
|
location: Location,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Gps {
|
|
latitude: f32,
|
|
longitude: f32,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Location {
|
|
precise: String,
|
|
broad: String,
|
|
}
|
|
|
|
fn vec_strings(vec: &Vec<String>) -> String {
|
|
let mut string = String::new();
|
|
string.push('[');
|
|
for el in vec {
|
|
string.push_str(&format!("{:?},", el));
|
|
}
|
|
string.push(']');
|
|
string
|
|
}
|
|
|
|
fn resume(dest: &std::path::Path, source: std::fs::File) {
|
|
let reader = std::io::BufReader::new(source);
|
|
let data: serde_json::Value = serde_json::from_reader(reader).expect("Failed to parse JSON");
|
|
let mut final_ser = String::new();
|
|
|
|
// Work
|
|
let work_json = &data["work"];
|
|
let work_data: Vec<Work> =
|
|
serde_json::from_value(work_json.clone()).expect("Failed to parse work");
|
|
let mut work_str = String::new();
|
|
work_str.push('[');
|
|
for work in &work_data {
|
|
work_str.push_str("Work {");
|
|
work_str.push_str(&format!("name: {:?},", work.name));
|
|
work_str.push_str(&format!("position: {:?},", work.position));
|
|
work_str.push_str(&format!("start_date: {:?},", work.start_date));
|
|
|
|
work_str.push_str(&format!(
|
|
"end_date: {},",
|
|
match &work.end_date {
|
|
Some(end) => format!("Some({:?})", end),
|
|
None => "None".into(),
|
|
}
|
|
));
|
|
|
|
// Optional struct
|
|
// TODO: refacto
|
|
match &work.link {
|
|
// TODO: enum with 2 variants for unavailable link
|
|
Some(link) => match link.not_available {
|
|
true => work_str.push_str(&format!(
|
|
"link: Some(ResumeLink {{ uri: {:?}, label: \"Not available\", not_available: true }}),",
|
|
link.uri
|
|
)),
|
|
false => work_str.push_str(&format!(
|
|
"link: Some(ResumeLink {{ uri: {:?}, label: {:?}, not_available: false }}),",
|
|
link.uri, link.label
|
|
)),
|
|
},
|
|
None => work_str.push_str("link: None,"),
|
|
}
|
|
|
|
// Struct
|
|
work_str.push_str(&format!(
|
|
"logo: Logo {{ file: {:?}, transparent_background: {} }},",
|
|
work.logo.file, work.logo.transparent_background
|
|
));
|
|
|
|
work_str.push_str(&format!("description: {:?},", work.description));
|
|
|
|
// Vector
|
|
let mut highlights = String::new();
|
|
highlights.push('[');
|
|
for high in &work.highlights {
|
|
highlights.push_str(&format!("{:?},", high));
|
|
}
|
|
highlights.push(']');
|
|
work_str.push_str(&format!("highlights: &{},", highlights));
|
|
|
|
// Vector
|
|
let mut technologies = String::new();
|
|
technologies.push('[');
|
|
for tech in &work.technologies {
|
|
technologies.push_str(&format!("{:?},", tech));
|
|
}
|
|
technologies.push(']');
|
|
work_str.push_str(&format!("technologies: &{},", technologies));
|
|
|
|
work_str.push_str("},\n");
|
|
}
|
|
work_str.push(']');
|
|
let work_ser = format!(
|
|
"pub const WORK: [Work; {}] = \n{};\n",
|
|
work_data.len(),
|
|
work_str
|
|
);
|
|
final_ser.push_str(&work_ser);
|
|
|
|
// Projects
|
|
let projects_json = &data["projects"];
|
|
let projects_data: Vec<Project> =
|
|
serde_json::from_value(projects_json.clone()).expect("Failed to parse projects");
|
|
let mut projects_str = String::new();
|
|
projects_str.push('[');
|
|
for project in &projects_data {
|
|
projects_str.push_str("Project {");
|
|
projects_str.push_str(&format!("name: {:?},", project.name));
|
|
projects_str.push_str(&format!("description: {:?},", project.description));
|
|
projects_str.push_str(&format!("start_date: {:?},", project.start_date));
|
|
|
|
projects_str.push_str(&format!(
|
|
"end_date: {},",
|
|
match &project.end_date {
|
|
Some(end) => format!("Some({:?})", end),
|
|
None => "None".into(),
|
|
}
|
|
));
|
|
|
|
// Optional struct
|
|
match &project.link {
|
|
// TODO: enum with 2 variants for unavailable link
|
|
Some(link) => match link.not_available {
|
|
true => projects_str.push_str(&format!(
|
|
"link: Some(ResumeLink {{ uri: {:?}, label: \"Not available\", not_available: true }}),",
|
|
link.uri
|
|
)),
|
|
false => projects_str.push_str(&format!(
|
|
"link: Some(ResumeLink {{ uri: {:?}, label: {:?}, not_available: false }}),",
|
|
link.uri, link.label
|
|
)),
|
|
},
|
|
None => projects_str.push_str("link: None,"),
|
|
}
|
|
|
|
// Vector
|
|
projects_str.push_str(&format!(
|
|
"presentation: &{},",
|
|
vec_strings(&project.presentation)
|
|
));
|
|
|
|
// Vector
|
|
projects_str.push_str(&format!(
|
|
"highlights : &{},",
|
|
vec_strings(&project.highlights)
|
|
));
|
|
|
|
// Vector
|
|
projects_str.push_str(&format!("keywords: &{},", vec_strings(&project.keywords)));
|
|
|
|
// Optional struct
|
|
match &project.logo {
|
|
Some(logo) => projects_str.push_str(&format!(
|
|
"logo: Some(Logo {{ file: {:?}, transparent_background: {} }}),",
|
|
logo.file, logo.transparent_background
|
|
)),
|
|
None => projects_str.push_str("logo: None,"),
|
|
}
|
|
|
|
// Optional struct
|
|
match &project.image {
|
|
Some(image) => projects_str.push_str(&format!(
|
|
"image: Some(Image {{ file: {:?}, position: {:?} }}),",
|
|
image.file, image.position
|
|
)),
|
|
None => projects_str.push_str("image: None,"),
|
|
}
|
|
|
|
projects_str.push_str("},\n");
|
|
}
|
|
projects_str.push(']');
|
|
let projects_ser = format!(
|
|
"pub const PROJECTS: [Project; {}] = \n{};\n",
|
|
projects_data.len(),
|
|
projects_str
|
|
);
|
|
final_ser.push_str(&projects_ser);
|
|
|
|
// Education
|
|
let education_json = &data["education"];
|
|
let education_data: Vec<Education> =
|
|
serde_json::from_value(education_json.clone()).expect("Failed to parse education");
|
|
let mut education_str = String::new();
|
|
education_str.push('[');
|
|
for education in &education_data {
|
|
education_str.push_str("Education {");
|
|
education_str.push_str(&format!("institution: {:?},", education.institution));
|
|
education_str.push_str(&format!("area: {:?},", education.area));
|
|
education_str.push_str(&format!("study_type: {:?},", education.study_type));
|
|
education_str.push_str(&format!("start_date: {:?},", education.start_date));
|
|
education_str.push_str(&format!(
|
|
"end_date: {},",
|
|
match &education.end_date {
|
|
Some(end) => format!("Some({:?})", end),
|
|
None => "None".into(),
|
|
}
|
|
));
|
|
|
|
// Optional struct
|
|
match &education.logo {
|
|
Some(logo) => education_str.push_str(&format!(
|
|
"logo: Some(Logo {{ file: {:?}, transparent_background: {} }}),",
|
|
logo.file, logo.transparent_background
|
|
)),
|
|
None => education_str.push_str("logo: None,"),
|
|
}
|
|
|
|
// Vector
|
|
let mut courses = String::new();
|
|
courses.push('[');
|
|
for course in &education.courses {
|
|
courses.push_str(&format!("{:?},", course));
|
|
}
|
|
courses.push(']');
|
|
education_str.push_str(&format!("courses: &{},", courses));
|
|
education_str.push_str("},\n");
|
|
}
|
|
education_str.push(']');
|
|
let education_ser = format!(
|
|
"pub const EDUCATION: [Education; {}] = \n{};\n",
|
|
education_data.len(),
|
|
education_str
|
|
);
|
|
final_ser.push_str(&education_ser);
|
|
|
|
std::fs::write(dest, final_ser).unwrap();
|
|
}
|
|
|
|
fn wallpapers(dest: &std::path::Path, source: std::fs::File) {
|
|
let reader = std::io::BufReader::new(source);
|
|
let wallpapers_data: Vec<Wallpaper> =
|
|
serde_json::from_reader(reader).expect("Failed to parse JSON");
|
|
let mut final_ser = String::new();
|
|
|
|
let mut wallpapers_str = String::new();
|
|
wallpapers_str.push('[');
|
|
|
|
for wallpaper in &wallpapers_data {
|
|
wallpapers_str.push_str("Wallpaper {");
|
|
wallpapers_str.push_str(&format!("filename: {:?},", wallpaper.filename));
|
|
wallpapers_str.push_str(&format!("date: {:?},", wallpaper.date));
|
|
wallpapers_str.push_str(&format!(
|
|
"gps: Gps {{ latitude: {}, longitude: {} }},",
|
|
wallpaper.gps.latitude, wallpaper.gps.longitude
|
|
));
|
|
wallpapers_str.push_str(&format!(
|
|
"location: Location {{ precise: {:?}, broad: {:?} }},",
|
|
wallpaper.location.precise, wallpaper.location.broad
|
|
));
|
|
wallpapers_str.push_str("},\n");
|
|
}
|
|
|
|
wallpapers_str.push(']');
|
|
let wallpapers_ser = format!(
|
|
"pub const WALLPAPERS: [Wallpaper; {}] = \n{};\n",
|
|
wallpapers_data.len(),
|
|
wallpapers_str
|
|
);
|
|
final_ser.push_str(&wallpapers_ser);
|
|
|
|
std::fs::write(dest, final_ser).unwrap();
|
|
}
|
|
|
|
fn main() {
|
|
println!("cargo::rerun-if-changed=resume.json");
|
|
println!("cargo::rerun-if-changed=wallpapers.json");
|
|
|
|
let out_dir = std::env::var_os("OUT_DIR").unwrap();
|
|
|
|
let resume_dest = std::path::Path::new(&out_dir).join("resume.rs");
|
|
let resume_source = std::fs::File::open("resume.json").expect("Failed to open file");
|
|
resume(&resume_dest, resume_source);
|
|
|
|
let wallpapers_dest = std::path::Path::new(&out_dir).join("wallpapers.rs");
|
|
match std::fs::File::open("wallpapers.json") {
|
|
Ok(source) => wallpapers(&wallpapers_dest, source),
|
|
Err(_) => {
|
|
std::fs::write(wallpapers_dest, "pub const WALLPAPERS: [Wallpaper; 0] = [];").unwrap();
|
|
println!("cargo::warning=skipping wallpapers, file not found");
|
|
}
|
|
}
|
|
}
|