Skip to content

Commit

Permalink
Use CodeFormater and add test (#2)
Browse files Browse the repository at this point in the history
* Use CodeFormater and add test

* Fix badge
  • Loading branch information
cecton authored Mar 7, 2021
1 parent 144edc7 commit 4eb232b
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 42 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: cecton
36 changes: 36 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: PR

on:
pull_request:
branches: [ main ]

env:
CARGO_TERM_COLOR: always

jobs:
cargo-test-and-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v2
with:
lfs: true

- uses: Swatinem/rust-cache@v1

- name: cargo test
uses: actions-rs/cargo@v1
with:
command: test

- name: rustfmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: -p generate-api -- --check

- name: clippy
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: -- -D warnings
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Latest Version](https://img.shields.io/crates/v/pure-rust-locales.svg)](https://crates.io/crates/gptman)
[![Latest Version](https://img.shields.io/crates/v/pure-rust-locales.svg)](https://crates.io/crates/pure-rust-locales)
![License](https://img.shields.io/crates/l/pure-rust-locales)
[![Docs.rs](https://docs.rs/pure-rust-locales/badge.svg)](https://docs.rs/pure-rust-locales)
![No dependencies](https://img.shields.io/badge/dependencies-none-success)
Expand Down
2 changes: 2 additions & 0 deletions generate-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
cargo_metadata = "0.12"
indenter = { version = "0.3", features = ["std"] }
itertools = "0.8"
nom = "5.0"
sha2 = "0.9"
52 changes: 34 additions & 18 deletions generate-api/src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use crate::parser;
use indenter::CodeFormatter;
use itertools::Itertools;
use std::collections::HashMap;
use std::fmt;
use std::fmt::Write;

fn generate_object(
f: &mut fmt::Formatter,
fn generate_object<W: Write>(
f: &mut CodeFormatter<W>,
object: &parser::Object,
locales: &HashMap<String, Vec<parser::Object>>,
) -> fmt::Result {
for (key, group) in &object
.values
.iter()
.filter(|x| x.1.len() > 0)
.filter(|x| !x.1.is_empty())
.sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
.group_by(|x| x.0.clone())
{
Expand All @@ -31,7 +33,7 @@ fn generate_object(
parser::Value::String(other_lang) => {
let other = locales
.get(other_lang)
.expect(&format!("unknown locale: {}", other_lang));
.unwrap_or_else(|| panic!("unknown locale: {}", other_lang));
let other_object = other
.iter()
.find(|x| x.name == object.name)
Expand All @@ -43,7 +45,7 @@ fn generate_object(
continue;
}

if group.len() == 1 && group[0].len() == 0 {
if group.len() == 1 && group[0].is_empty() {
return Ok(());
} else if group.len() == 1 && group[0].len() == 1 {
let singleton = &group[0][0];
Expand All @@ -53,7 +55,7 @@ fn generate_object(
f,
r#"
/// `{x:?}`
pub const {key}: &'static str = {x:?};
pub const {key}: &str = {x:?};
"#,
key = key,
x = x
Expand All @@ -77,7 +79,7 @@ fn generate_object(
f,
r#"
/// `&[{x}]`
pub const {key}: &'static [&'static str] = &[{x}];
pub const {key}: &[&str] = &[{x}];
"#,
key = key,
x = formatted
Expand All @@ -86,7 +88,7 @@ fn generate_object(
f,
r#"
/// `&[{x}]`
pub const {key}: &'static [i64] = &[{x}];
pub const {key}: &[i64] = &[{x}];
"#,
key = key,
x = formatted
Expand Down Expand Up @@ -128,18 +130,19 @@ fn generate_object(
parser::Value::Raw(_) | parser::Value::String(_) => write!(
f,
r#"
pub const {}: &'static [&'static [&'static str]] = &[
pub const {}: &[&[&str]] = &[
"#,
key
)?,
parser::Value::Integer(_) => write!(
f,
r#"
pub const {}: &'static [&'static [i64]] = &[
pub const {}: &[&[i64]] = &[
"#,
key,
)?,
}
f.indent(1);

for values in group.iter() {
write!(
Expand All @@ -151,6 +154,7 @@ fn generate_object(
)?;
}

f.dedent(1);
write!(
f,
r#"
Expand All @@ -165,20 +169,22 @@ fn generate_object(
Ok(())
}

fn generate_locale(
f: &mut fmt::Formatter,
fn generate_locale<W: Write>(
f: &mut CodeFormatter<W>,
lang_normalized: &str,
objects: &Vec<parser::Object>,
objects: &[parser::Object],
locales: &HashMap<String, Vec<parser::Object>>,
) -> fmt::Result {
write!(
f,
r#"
#[allow(non_snake_case,non_camel_case_types,dead_code,unused_imports)]
pub mod {} {{
"#,
lang_normalized,
)?;
f.indent(1);

for object in objects.iter().sorted_by_key(|x| x.name.to_string()) {
if object.name == "LC_COLLATE"
Expand All @@ -190,6 +196,7 @@ fn generate_locale(
continue;
} else if object.values.len() == 1 {
let (key, value) = &object.values[0];
#[allow(clippy::single_match)]
match key.as_str() {
"copy" => {
assert_eq!(value.len(), 1);
Expand All @@ -215,35 +222,38 @@ fn generate_locale(
"#,
object.name,
)?;
f.indent(1);
generate_object(f, &object, locales)?;
f.dedent(1);
write!(
f,
r#"
}}
"#,
)?;
}
}

f.dedent(1);
write!(
f,
r#"
}}
"#,
)
}

fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Result {
fn generate_variants<W: Write>(f: &mut CodeFormatter<W>, langs: &[(&str, &str)]) -> fmt::Result {
write!(
f,
r#"
#[allow(non_camel_case_types,dead_code)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Locale {{
"#,
)?;
f.indent(1);

for (lang, norm) in langs {
write!(
Expand All @@ -257,6 +267,7 @@ fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Res
)?;
}

f.dedent(1);
write!(
f,
r#"
Expand All @@ -269,6 +280,7 @@ fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Res
match i {{
"#,
)?;
f.indent(3);

for (lang, norm) in langs {
write!(
Expand All @@ -281,6 +293,7 @@ fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Res
)?;
}

f.dedent(3);
write!(
f,
r#"
Expand All @@ -295,6 +308,7 @@ fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Res
match $locale {{
"#,
)?;
f.indent(3);

for (_, norm) in langs {
write!(
Expand All @@ -305,6 +319,7 @@ fn generate_variants(f: &mut fmt::Formatter, langs: &[(&str, &str)]) -> fmt::Res
norm = norm,
)?;
}
f.dedent(3);

write!(
f,
Expand All @@ -321,6 +336,7 @@ pub struct CodeGenerator(pub HashMap<String, Vec<parser::Object>>);

impl fmt::Display for CodeGenerator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut f = CodeFormatter::new(f, " ");
write!(
f,
r#"
Expand All @@ -342,14 +358,14 @@ impl fmt::Display for CodeGenerator {
let mut sorted: Vec<_> = locales.iter().collect();
sorted.sort_unstable_by_key(|(lang, _)| lang.to_string());
for (lang, objects) in sorted.iter() {
generate_locale(f, normalized[lang].as_str(), &objects, locales)?;
generate_locale(&mut f, normalized[lang].as_str(), &objects, locales)?;
}

let mut sorted: Vec<_> = locales
.iter()
.map(|(lang, _)| (lang.as_str(), normalized[lang].as_str()))
.collect();
sorted.sort_unstable_by_key(|(lang, _)| lang.to_string());
generate_variants(f, &sorted)
generate_variants(&mut f, &sorted)
}
}
42 changes: 26 additions & 16 deletions generate-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ pub mod parser;

use anyhow::{bail, Result};
use cargo_metadata::MetadataCommand;
use sha2::{Digest, Sha256};
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io;
use std::io::{BufWriter, Write};

fn main() -> Result<()> {
let metadata = MetadataCommand::new().exec()?;

println!("Reading data...");
eprintln!("Reading data...");

let locales_path = metadata.workspace_root.join("localedata").join("locales");
let mut locales = HashMap::new();
Expand All @@ -28,31 +31,38 @@ fn main() -> Result<()> {

let path = entry.path();
if let Ok(input) = std::fs::read_to_string(&path) {
println!("{}", path.display());
eprintln!("{}", path.display());
let objects = parser::parse(&input)?;
locales.insert(lang.to_string(), objects);
}
}

let dest_path = metadata.workspace_root.join("src").join("lib.rs");
let mut f = BufWriter::new(fs::File::create(&dest_path)?);
let lib_file = metadata.workspace_root.join("src").join("lib.rs");

println!("Writing to file `{}`...", dest_path.display());
if matches!(env::var("CHECK"), Ok(_)) {
eprintln!("Calculating checksum...");
let mut f = Sha256::default();

write!(f, "{}", generator::CodeGenerator(locales))?;
write!(f, "{}", generator::CodeGenerator(locales))?;

drop(f);
let expected = f.finalize();
eprintln!("expected: {:x}", expected);

let status = std::process::Command::new("cargo")
.current_dir(metadata.workspace_root)
.args(&["fmt", "--"])
.arg(dest_path)
.status()
.unwrap();
let mut hasher = Sha256::default();
io::copy(&mut fs::File::open(&lib_file)?, &mut hasher)?;
let got = hasher.finalize();
eprintln!("got: {:x}", got);

if status.success() {
Ok(())
if expected != got {
bail!(
"lib.rs file has been modified! Please run `cargo run -p generate-api --release`",
);
}
} else {
bail!("command `cargo fmt` failed");
eprintln!("Writing to file `{}`...", lib_file.display());
let mut f = BufWriter::new(fs::File::create(&lib_file)?);
write!(f, "{}", generator::CodeGenerator(locales))?;
}

Ok(())
}
7 changes: 2 additions & 5 deletions generate-api/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,7 @@ fn value<'a, E: ParseError<&'a str>>(
alt((
map_res(integer, |s| i64::from_str_radix(s, 10).map(Value::Integer)),
map(|x| string(x, escape_char), Value::String),
map(
|x| parse_raw(x, escape_char, comment_char),
|s| Value::Raw(String::from(s)),
),
map(|x| parse_raw(x, escape_char, comment_char), Value::Raw),
)),
)(i)
}
Expand Down Expand Up @@ -250,7 +247,7 @@ fn object<'a, E: ParseError<&'a str>>(
name: name.to_string(),
values: values
.into_iter()
.map(|(k, v)| (k.to_string(), v.into_iter().filter_map(|x| x).collect()))
.map(|(k, v)| (k, v.into_iter().filter_map(|x| x).collect()))
.collect(),
},
))
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Git LFS file not shown
Loading

0 comments on commit 4eb232b

Please sign in to comment.