blob: 559fbb18b354e8a539cb51037c3bce978dd0b123 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use anyhow::Error;
use lazy_static::lazy_static;
use regex::Regex;
use std::env;
use std::fs::File;
use std::io::Write;
use unic_ucd_block::{Block, BlockIter};
lazy_static! {
static ref REGEX_NON_IDENTIFIER: Regex = Regex::new(r"[^A-Za-z0-9]+").unwrap();
}
const PREAMBLE: &str = r#"// Generated using //garnet/bin/fonts/unicode_blocks:generate_unicode_blocks. Do not edit.
mod blocks {
use lazy_static::lazy_static;
use unic_char_range::CharRange;
use unic_ucd_block::{Block, BlockIter};
"#;
const BLOCKS_VEC: &str = r#"
lazy_static! {
static ref BLOCKS: Vec<Block> = BlockIter::new().collect();
}
"#;
pub fn generate_unicode_blocks_enum() -> String {
let mut s = String::new();
s.push_str(
r#"
/// Compile-time identifiers for a [Unicode Block](unic_ucd_block::Block).
///
/// Use `.block()` to get a reference to the actual `Block` instance.
#[derive(Debug)]
pub enum UnicodeBlockId {
"#,
);
for block in BlockIter::new() {
s.push_str(&format!(" {},\n", block.enum_id()));
}
s.push_str(" }\n");
s
}
pub fn generate_impl() -> String {
let mut s = String::new();
s.push_str(
r#"
impl UnicodeBlockId {
/// Get the block's name.
pub fn name(&self) -> &str {
self.block().name
}
/// Get the block's `CharRange`.
pub fn char_range(&self) -> CharRange {
self.block().range
}
/// Get a reference to the `Block` that this ID represents.
pub fn block(&self) -> &'static Block {
&BLOCKS[self.idx()]
}
fn idx(&self) -> usize {
match self {
"#,
);
let mut idx: usize = 0;
for block in BlockIter::new() {
s.push_str(&format!(" UnicodeBlockId::{} => {},\n", block.enum_id(), idx));
idx += 1;
}
s.push_str(" }\n"); // match
s.push_str(" }\n"); // fn idx
s.push_str(" }\n"); // impl UnicodeBlockId
s.push_str(
r#"
impl From<&UnicodeBlockId> for CharRange {
fn from(source: &UnicodeBlockId) -> Self {
source.char_range()
}
}
"#,
);
s
}
const EPILOGUE: &str = r#"
}
pub use blocks::UnicodeBlockId;
"#;
trait BlockExt {
fn enum_id(&self) -> String;
}
impl BlockExt for Block {
fn enum_id(&self) -> String {
let segments: Vec<&str> = REGEX_NON_IDENTIFIER.split(self.name).collect();
(&segments).join("")
}
}
fn main() -> Result<(), Error> {
let args: Vec<String> = env::args().collect();
let mut out_file = File::create(args[1].clone())?;
write!(out_file, "{}", PREAMBLE)?;
write!(out_file, "{}", BLOCKS_VEC)?;
write!(out_file, "{}", generate_unicode_blocks_enum())?;
write!(out_file, "{}", generate_impl())?;
write!(out_file, "{}", EPILOGUE)?;
Ok(())
}