summaryrefslogtreecommitdiffstats
path: root/vendor/xflags-macros/src/update.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/xflags-macros/src/update.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/xflags-macros/src/update.rs')
-rw-r--r--vendor/xflags-macros/src/update.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/vendor/xflags-macros/src/update.rs b/vendor/xflags-macros/src/update.rs
new file mode 100644
index 000000000..e476e37aa
--- /dev/null
+++ b/vendor/xflags-macros/src/update.rs
@@ -0,0 +1,98 @@
+use std::{fs, ops::Range, path::Path};
+
+pub(crate) fn in_place(api: &str, path: &Path) {
+ let path = {
+ let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
+ Path::new(&dir).join(path)
+ };
+
+ let mut text =
+ fs::read_to_string(&path).unwrap_or_else(|_| panic!("failed to read {:?}", path));
+
+ let (insert_to, indent) = locate(&text);
+
+ let api: String =
+ with_preamble(api)
+ .lines()
+ .map(|it| {
+ if it.trim().is_empty() {
+ "\n".to_string()
+ } else {
+ format!("{}{}\n", indent, it)
+ }
+ })
+ .collect();
+ text.replace_range(insert_to, &api);
+
+ fs::write(&path, text.as_bytes()).unwrap();
+}
+
+pub(crate) fn stdout(api: &str) {
+ print!("{}", with_preamble(api))
+}
+
+fn with_preamble(api: &str) -> String {
+ format!(
+ "\
+// generated start
+// The following code is generated by `xflags` macro.
+// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
+{}
+// generated end
+",
+ api.trim()
+ )
+}
+
+fn locate(text: &str) -> (Range<usize>, String) {
+ if let Some(it) = locate_existing(text) {
+ return it;
+ }
+ if let Some(it) = locate_new(text) {
+ return it;
+ }
+ panic!("failed to update xflags in place")
+}
+
+fn locate_existing(text: &str) -> Option<(Range<usize>, String)> {
+ let start_idx = text.find("// generated start")?;
+ let start_idx = newline_before(text, start_idx);
+
+ let end_idx = text.find("// generated end")?;
+ let end_idx = newline_after(text, end_idx);
+
+ let indent = indent_at(text, start_idx);
+
+ Some((start_idx..end_idx, indent))
+}
+
+fn newline_before(text: &str, start_idx: usize) -> usize {
+ text[..start_idx].rfind('\n').map_or(start_idx, |it| it + 1)
+}
+
+fn newline_after(text: &str, start_idx: usize) -> usize {
+ start_idx + text[start_idx..].find('\n').map_or(text[start_idx..].len(), |it| it + 1)
+}
+
+fn indent_at(text: &str, start_idx: usize) -> String {
+ text[start_idx..].chars().take_while(|&it| it == ' ').collect()
+}
+
+fn locate_new(text: &str) -> Option<(Range<usize>, String)> {
+ let mut idx = text.find("xflags!")?;
+ let mut lvl = 0i32;
+ for c in text[idx..].chars() {
+ idx += c.len_utf8();
+ match c {
+ '{' => lvl += 1,
+ '}' if lvl == 1 => break,
+ '}' => lvl -= 1,
+ _ => (),
+ }
+ }
+ let indent = indent_at(text, newline_before(text, idx));
+ if text[idx..].starts_with('\n') {
+ idx += 1;
+ }
+ Some((idx..idx, indent))
+}