build script to convert json locales at compile time

This commit is contained in:
Alessandro Pellizzari 2018-12-05 18:42:47 +00:00
parent 64ea230a2b
commit 06c7199755
4 changed files with 196 additions and 71 deletions

View file

@ -2,7 +2,7 @@
name = "chrono-locale" name = "chrono-locale"
version = "0.1.0" version = "0.1.0"
authors = ["Alessandro Pellizzari <alex@amiran.it>"] authors = ["Alessandro Pellizzari <alex@amiran.it>"]
# build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
chrono = "0.4" chrono = "0.4"

164
build.rs
View file

@ -1,62 +1,174 @@
extern crate walkdir; extern crate walkdir;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::{Write, Read, Error as IoError};
use std::path::Path; use std::path::Path;
use serde_json::{Error as JsonError};
use walkdir::WalkDir; use walkdir::{WalkDir, DirEntry};
#[derive(Deserialize)]
pub struct Locale { pub struct Locale {
short_months: Vec<String>, short_months: Option<Vec<String>>,
long_months: Vec<String>, long_months: Option<Vec<String>>,
short_weekdays: Vec<String>, short_weekdays: Option<Vec<String>>,
long_weekdays: Vec<String>, long_weekdays: Option<Vec<String>>,
} }
fn main() { fn main() {
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("locales.rs"); let dest_path = Path::new(&out_dir).join("locales.rs");
let mut f = File::create(&dest_path).unwrap(); let mut f = File::create(&dest_path).unwrap();
f.write_all(r###" let _ = f.write_all(r#####"lazy_static! {
use std::collections::HashMap; pub static ref LOCALES: Locales = {
let mut res = Locales {
short_months: HashMap::new(),
long_months: HashMap::new(),
short_weekdays: HashMap::new(),
long_weekdays: HashMap::new(),
};
pub type Locales = HashMap<String, Locale>; res.short_months.insert(
"C".into(),
vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
);
pub struct Locale { res.long_months.insert(
short_months: Vec<String>, "C".into(),
long_months: Vec<String>, vec![
short_weekdays: Vec<String>, "January",
long_weekdays: Vec<String>, "February",
} "March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
],
);
lazy_static! { res.short_weekdays
static ref LOCALES: Locales = { .insert("C".into(), vec!["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]);
let mut res = HashMap::new();
"###.as_bytes()).unwrap();
res.long_weekdays.insert(
"C".into(),
vec!["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
);
"#####.as_bytes());
println!("Building..."); println!("Building...");
for entry in WalkDir::new("locales") { for entry in WalkDir::new("locales") {
let entry = entry.unwrap(); let entry = entry.unwrap();
println!("{}", entry.path().display()); println!("Found {}", entry.path().display());
if entry.path().extension().map(|e| e != "json").unwrap_or(false) { if entry.path().extension().map(|e| e != "json").unwrap_or(false) {
println!("Not a json file"); println!("Not a json file");
continue continue
} }
let locale_name = entry.path().file_stem().map(|n| n.to_string_lossy());
if locale_name.is_none() {
continue;
} }
f.write_all(r###" let locale_name = locale_name.unwrap().to_string();
if let Ok(locale_data) = load_locale(&entry) {
if let Some(long_months) = locale_data.long_months {
if long_months.len() == 12 {
let _ = f.write_all(format!(
"res.long_months.insert(\"{}\".into(), vec![{}]);\n",
locale_name,
long_months
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(",")
).as_bytes()).unwrap();
}
}
res if let Some(short_months) = locale_data.short_months {
if short_months.len() == 12 {
let _ = f.write_all(format!(
"res.short_months.insert(\"{}\".into(), vec![{}]);\n",
locale_name,
short_months
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(",")
).as_bytes()).unwrap();
}
}
if let Some(long_weekdays) = locale_data.long_weekdays {
if long_weekdays.len() == 7 {
let _ = f.write_all(format!(
"res.long_weekdays.insert(\"{}\".into(), vec![{}]);\n",
locale_name,
long_weekdays
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(",")
).as_bytes()).unwrap();
}
}
if let Some(short_weekdays) = locale_data.short_weekdays {
if short_weekdays.len() == 7 {
let _ = f.write_all(format!(
"res.short_weekdays.insert(\"{}\".into(), vec![{}]);\n",
locale_name,
short_weekdays
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(",")
).as_bytes()).unwrap();
}
}
}
}
let _ = f.write_all(r####" res
}; };
} }
"###.as_bytes()).unwrap(); "####.as_bytes());
}
fn load_locale(entry: &DirEntry) -> Result<Locale, BuildError> {
let mut locale_data = String::new();
let mut f = File::open(entry.path())?;
f.read_to_string(&mut locale_data)?;
let locale = serde_json::from_str::<Locale>(&locale_data)?;
Ok(locale)
}
enum BuildError {
Io(IoError),
Json(JsonError),
}
impl From<IoError> for BuildError {
fn from(e: IoError) -> Self {
BuildError::Io(e)
}
}
impl From<JsonError> for BuildError {
fn from(e: JsonError) -> Self {
BuildError::Json(e)
}
} }

55
src/locales-old.rs Normal file
View file

@ -0,0 +1,55 @@
// This file will be overwritten by build.rs during compilation
use std::collections::HashMap;
#[derive(Debug)]
pub struct Locales {
pub short_months: HashMap<String, Vec<&'static str>>,
pub long_months: HashMap<String, Vec<&'static str>>,
pub short_weekdays: HashMap<String, Vec<&'static str>>,
pub long_weekdays: HashMap<String, Vec<&'static str>>,
}
lazy_static! {
pub static ref LOCALES: Locales = {
let mut res = Locales {
short_months: HashMap::new(),
long_months: HashMap::new(),
short_weekdays: HashMap::new(),
long_weekdays: HashMap::new(),
};
res.short_months.insert(
"C".into(),
vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
);
res.long_months.insert(
"C".into(),
vec![
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
],
);
res.short_weekdays
.insert("C".into(), vec!["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]);
res.long_weekdays.insert(
"C".into(),
vec!["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
);
res
};
}

View file

@ -1,7 +1,6 @@
// This file will be overwritten by build.rs during compilation
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)]
pub struct Locales { pub struct Locales {
pub short_months: HashMap<String, Vec<&'static str>>, pub short_months: HashMap<String, Vec<&'static str>>,
pub long_months: HashMap<String, Vec<&'static str>>, pub long_months: HashMap<String, Vec<&'static str>>,
@ -9,46 +8,5 @@ pub struct Locales {
pub long_weekdays: HashMap<String, Vec<&'static str>>, pub long_weekdays: HashMap<String, Vec<&'static str>>,
} }
lazy_static! { include!(concat!(env!("OUT_DIR"), "/locales.rs"));
pub static ref LOCALES: Locales = {
let mut res = Locales {
short_months: HashMap::new(),
long_months: HashMap::new(),
short_weekdays: HashMap::new(),
long_weekdays: HashMap::new(),
};
res.short_months.insert(
"C".into(),
vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
);
res.long_months.insert(
"C".into(),
vec![
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
],
);
res.short_weekdays
.insert("C".into(), vec!["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]);
res.long_weekdays.insert(
"C".into(),
vec!["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
);
res
};
}