123use std::{fs, path::Path};45use anyhow::Result;6use xshell::{Shell, cmd};78910pub fn ensure_file_contents(file: &Path, contents: &str) {11 if let Ok(old_contents) = fs::read_to_string(file) {12 if normalize_newlines(&old_contents) == normalize_newlines(contents) {13 14 return;15 }16 }1718 eprintln!("{} was not up-to-date, updating", file.display());19 if let Some(parent) = file.parent() {20 let _ = fs::create_dir_all(parent);21 }22 fs::write(file, contents).unwrap();23}242526fn normalize_newlines(s: &str) -> String {27 s.replace("\r\n", "\n")28}2930pub fn pluralize(s: &str) -> String {31 32 format!("{s}s")33}3435pub fn to_upper_snake_case(s: &str) -> String {36 let mut buf = String::with_capacity(s.len());37 let mut prev = false;38 for c in s.chars() {39 if c.is_ascii_uppercase() && prev {40 buf.push('_');41 }42 prev = true;4344 buf.push(c.to_ascii_uppercase());45 }46 buf47}48pub fn to_lower_snake_case(s: &str) -> String {49 let mut buf = String::with_capacity(s.len());50 let mut prev = false;51 for c in s.chars() {52 if c.is_ascii_uppercase() && prev {53 buf.push('_');54 }55 prev = true;5657 buf.push(c.to_ascii_lowercase());58 }59 buf60}6162pub fn to_pascal_case(s: &str) -> String {63 let mut buf = String::with_capacity(s.len());64 let mut prev_is_underscore = true;65 for c in s.chars() {66 if c == '_' {67 prev_is_underscore = true;68 } else if prev_is_underscore {69 buf.push(c.to_ascii_uppercase());70 prev_is_underscore = false;71 } else {72 buf.push(c.to_ascii_lowercase());73 }74 }75 buf76}7778pub fn reformat(text: &str) -> Result<String> {79 80 81 let sh = Shell::new()?;82 let stdout = cmd!(sh, "rustfmt").stdin(text).read()?;83 Ok(format!(84 "{}\n\n{}\n",85 "//! This is a generated file, please do not edit manually. Changes can be86//! made in codegeneration that lives in `xtask` top-level dir.",87 stdout88 ))89}