1use std::{fs, path::Path};23use anyhow::Result;4use xshell::{cmd, Shell};5678pub fn ensure_file_contents(file: &Path, contents: &str) -> Result<()> {9 if let Ok(old_contents) = fs::read_to_string(file) {10 if normalize_newlines(&old_contents) == normalize_newlines(contents) {11 12 return Ok(());13 }14 }1516 eprintln!("{} was not up-to-date, updating", file.display());17 if let Some(parent) = file.parent() {18 let _ = fs::create_dir_all(parent);19 }20 fs::write(file, contents).unwrap();21 Ok(())22}232425fn normalize_newlines(s: &str) -> String {26 s.replace("\r\n", "\n")27}2829pub(crate) fn pluralize(s: &str) -> String {30 format!("{}s", s)31}3233pub fn to_upper_snake_case(s: &str) -> String {34 let mut buf = String::with_capacity(s.len());35 let mut prev = false;36 for c in s.chars() {37 if c.is_ascii_uppercase() && prev {38 buf.push('_')39 }40 prev = true;4142 buf.push(c.to_ascii_uppercase());43 }44 buf45}46pub fn to_lower_snake_case(s: &str) -> String {47 let mut buf = String::with_capacity(s.len());48 let mut prev = false;49 for c in s.chars() {50 if c.is_ascii_uppercase() && prev {51 buf.push('_')52 }53 prev = true;5455 buf.push(c.to_ascii_lowercase());56 }57 buf58}5960pub fn to_pascal_case(s: &str) -> String {61 let mut buf = String::with_capacity(s.len());62 let mut prev_is_underscore = true;63 for c in s.chars() {64 if c == '_' {65 prev_is_underscore = true;66 } else if prev_is_underscore {67 buf.push(c.to_ascii_uppercase());68 prev_is_underscore = false;69 } else {70 buf.push(c.to_ascii_lowercase());71 }72 }73 buf74}7576pub fn reformat(text: &str) -> Result<String> {77 78 79 let sh = Shell::new()?;80 let stdout = cmd!(sh, "rustfmt").stdin(text).read()?;81 Ok(format!(82 "{}\n\n{}\n",83 "//! This is a generated file, please do not edit manually. Changes can be84//! made in codegeneration that lives in `xtask` top-level dir.",85 stdout86 ))87}