//! Parse the output of rustc's `.d` dep-info file. //! //! Used by the hot-reloading engine and other libraries to provide higher quality dependency analysis //! for the user's project. use std::path::{Path, PathBuf}; #[non_exhaustive] #[derive(Debug, thiserror::Error)] pub enum DepInfoParseError { /// The input was malformed - maybe this `.d` format is no longer supported? #[error("Malformed input")] MalformedInput, /// An env var could not be escaped or parsed - this might be a bug in rustc. #[error("Failed to parse env var name")] InvalidEnvVarName, } #[non_exhaustive] #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct RustcDepInfo { /// The list of files that the main target in the dep-info file depends on. pub files: Vec, /// The list of environment variables we found that the rustc compilation /// depends on. /// /// The first element of the pair is the name of the env var and the second /// item is the value. `Some` means that the env var was set, and `None` /// means that the env var wasn't actually set and the compilation depends /// on it not being set. pub env: Vec<(String, Option)>, } impl std::str::FromStr for RustcDepInfo { type Err = DepInfoParseError; fn from_str(s: &str) -> Result { Self::new(s) } } impl RustcDepInfo { pub fn from_file(path: &Path) -> Result { let contents = std::fs::read_to_string(path).map_err(|_| DepInfoParseError::MalformedInput)?; RustcDepInfo::new(&contents) } /// Parse the `.d` dep-info file generated by rustc. pub fn new(contents: &str) -> Result { let mut ret = RustcDepInfo::default(); let mut found_deps = false; for line in contents.lines() { if let Some(rest) = line.strip_prefix("# env-dep:") { let mut parts = rest.splitn(2, '='); let env_var = match parts.next() { Some(s) => s, None => continue, }; let env_val = match parts.next() { Some(s) => Some(unescape_env(s)?), None => None, }; ret.env.push((unescape_env(env_var)?, env_val)); } else if let Some(pos) = line.find(": ") { if found_deps { continue; } found_deps = true; let mut deps = line[pos + 2..].split_whitespace(); while let Some(s) = deps.next() { let mut file = s.to_string(); while file.ends_with('\\') { file.pop(); file.push(' '); file.push_str(deps.next().ok_or(DepInfoParseError::MalformedInput)?); } ret.files.push(file.into()); } } } return Ok(ret); // rustc tries to fit env var names and values all on a single line, which // means it needs to escape `\r` and `\n`. The escape syntax used is "\n" // which means that `\` also needs to be escaped. fn unescape_env(s: &str) -> Result { let mut ret = String::with_capacity(s.len()); let mut chars = s.chars(); while let Some(c) = chars.next() { if c != '\\' { ret.push(c); continue; } match chars.next() { Some('\\') => ret.push('\\'), Some('n') => ret.push('\n'), Some('r') => ret.push('\r'), Some(_) => return Err(DepInfoParseError::InvalidEnvVarName), None => return Err(DepInfoParseError::InvalidEnvVarName), } } Ok(ret) } } } #[cfg(test)] mod tests { use super::*; #[test] fn parses_from_path() { let contents = include_str!("./dx.d"); let info: RustcDepInfo = contents.parse().unwrap(); let answer = vec![ "/dioxus/packages/autofmt/README.md", "/dioxus/packages/autofmt/src/buffer.rs", "/dioxus/packages/autofmt/src/collect_macros.rs", "/dioxus/packages/autofmt/src/indent.rs", "/dioxus/packages/autofmt/src/lib.rs", "/dioxus/packages/autofmt/src/prettier_please.rs", "/dioxus/packages/autofmt/src/writer.rs", "/dioxus/packages/check/README.md", "/dioxus/packages/check/src/check.rs", "/dioxus/packages/check/src/issues.rs", "/dioxus/packages/check/src/lib.rs", "/dioxus/packages/check/src/metadata.rs", "/dioxus/packages/cli/README.md", "/dioxus/packages/cli/assets/android/MainActivity.kt.hbs", "/dioxus/packages/cli/assets/android/gen/app/build.gradle.kts.hbs", "/dioxus/packages/cli/assets/android/gen/app/proguard-rules.pro", "/dioxus/packages/cli/assets/android/gen/app/src/main/AndroidManifest.xml.hbs", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/drawable/ic_launcher_background.xml", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/drawable-v24/ic_launcher_foreground.xml", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-hdpi/ic_launcher.webp", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-mdpi/ic_launcher.webp", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-xhdpi/ic_launcher.webp", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/values/colors.xml", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/values/strings.xml.hbs", "/dioxus/packages/cli/assets/android/gen/app/src/main/res/values/styles.xml", "/dioxus/packages/cli/assets/android/gen/build.gradle.kts", "/dioxus/packages/cli/assets/android/gen/gradle/wrapper/gradle-wrapper.jar", "/dioxus/packages/cli/assets/android/gen/gradle/wrapper/gradle-wrapper.properties", "/dioxus/packages/cli/assets/android/gen/gradle.properties", "/dioxus/packages/cli/assets/android/gen/gradlew", "/dioxus/packages/cli/assets/android/gen/gradlew.bat", "/dioxus/packages/cli/assets/android/gen/settings.gradle", "/dioxus/packages/cli/assets/dioxus.toml", "/dioxus/packages/cli/assets/ios/ios.plist.hbs", "/dioxus/packages/cli/assets/macos/mac.plist.hbs", "/dioxus/packages/cli/assets/web/index.html", "/dioxus/packages/cli/assets/web/loading.html", "/dioxus/packages/cli/assets/web/toast.html", "/dioxus/packages/cli/build.rs", "/dioxus/packages/cli/src/build/builder.rs", "/dioxus/packages/cli/src/build/bundle.rs", "/dioxus/packages/cli/src/build/mod.rs", "/dioxus/packages/cli/src/build/prerender.rs", "/dioxus/packages/cli/src/build/progress.rs", "/dioxus/packages/cli/src/build/request.rs", "/dioxus/packages/cli/src/build/templates.rs", "/dioxus/packages/cli/src/build/verify.rs", "/dioxus/packages/cli/src/build/web.rs", "/dioxus/packages/cli/src/bundle_utils.rs", "/dioxus/packages/cli/src/cli/autoformat.rs", "/dioxus/packages/cli/src/cli/build.rs", "/dioxus/packages/cli/src/cli/bundle.rs", "/dioxus/packages/cli/src/cli/check.rs", "/dioxus/packages/cli/src/cli/clean.rs", "/dioxus/packages/cli/src/cli/config.rs", "/dioxus/packages/cli/src/cli/create.rs", "/dioxus/packages/cli/src/cli/init.rs", "/dioxus/packages/cli/src/cli/link.rs", "/dioxus/packages/cli/src/cli/mod.rs", "/dioxus/packages/cli/src/cli/run.rs", "/dioxus/packages/cli/src/cli/serve.rs", "/dioxus/packages/cli/src/cli/target.rs", "/dioxus/packages/cli/src/cli/translate.rs", "/dioxus/packages/cli/src/cli/verbosity.rs", "/dioxus/packages/cli/src/config/app.rs", "/dioxus/packages/cli/src/config/bundle.rs", "/dioxus/packages/cli/src/config/desktop.rs", "/dioxus/packages/cli/src/config/dioxus_config.rs", "/dioxus/packages/cli/src/config/serve.rs", "/dioxus/packages/cli/src/config/web.rs", "/dioxus/packages/cli/src/config.rs", "/dioxus/packages/cli/src/dioxus_crate.rs", "/dioxus/packages/cli/src/dx_build_info.rs", "/dioxus/packages/cli/src/error.rs", "/dioxus/packages/cli/src/fastfs.rs", "/dioxus/packages/cli/src/filemap.rs", "/dioxus/packages/cli/src/logging.rs", "/dioxus/packages/cli/src/main.rs", "/dioxus/packages/cli/src/metadata.rs", "/dioxus/packages/cli/src/platform.rs", "/dioxus/packages/cli/src/rustc.rs", "/dioxus/packages/cli/src/serve/ansi_buffer.rs", "/dioxus/packages/cli/src/serve/detect.rs", "/dioxus/packages/cli/src/serve/handle.rs", "/dioxus/packages/cli/src/serve/mod.rs", "/dioxus/packages/cli/src/serve/output.rs", "/dioxus/packages/cli/src/serve/proxy.rs", "/dioxus/packages/cli/src/serve/runner.rs", "/dioxus/packages/cli/src/serve/server.rs", "/dioxus/packages/cli/src/serve/update.rs", "/dioxus/packages/cli/src/serve/watcher.rs", "/dioxus/packages/cli/src/settings.rs", "/dioxus/packages/cli/src/wasm_bindgen.rs", "/dioxus/packages/cli-config/src/lib.rs", "/dioxus/packages/cli-opt/src/css.rs", "/dioxus/packages/cli-opt/src/file.rs", "/dioxus/packages/cli-opt/src/folder.rs", "/dioxus/packages/cli-opt/src/image/jpg.rs", "/dioxus/packages/cli-opt/src/image/mod.rs", "/dioxus/packages/cli-opt/src/image/png.rs", "/dioxus/packages/cli-opt/src/js.rs", "/dioxus/packages/cli-opt/src/json.rs", "/dioxus/packages/cli-opt/src/lib.rs", "/dioxus/packages/config-macro/README.md", "/dioxus/packages/config-macro/src/lib.rs", "/dioxus/packages/const-serialize/README.md", "/dioxus/packages/const-serialize/src/const_buffers.rs", "/dioxus/packages/const-serialize/src/const_vec.rs", "/dioxus/packages/const-serialize/src/lib.rs", "/dioxus/packages/const-serialize-macro/src/lib.rs", "/dioxus/packages/core/README.md", "/dioxus/packages/core/docs/common_spawn_errors.md", "/dioxus/packages/core/docs/reactivity.md", "/dioxus/packages/core/src/any_props.rs", "/dioxus/packages/core/src/arena.rs", "/dioxus/packages/core/src/diff/component.rs", "/dioxus/packages/core/src/diff/iterator.rs", "/dioxus/packages/core/src/diff/mod.rs", "/dioxus/packages/core/src/diff/node.rs", "/dioxus/packages/core/src/effect.rs", "/dioxus/packages/core/src/error_boundary.rs", "/dioxus/packages/core/src/events.rs", "/dioxus/packages/core/src/fragment.rs", "/dioxus/packages/core/src/generational_box.rs", "/dioxus/packages/core/src/global_context.rs", "/dioxus/packages/core/src/hotreload_utils.rs", "/dioxus/packages/core/src/launch.rs", "/dioxus/packages/core/src/lib.rs", "/dioxus/packages/core/src/mutations.rs", "/dioxus/packages/core/src/nodes.rs", "/dioxus/packages/core/src/properties.rs", "/dioxus/packages/core/src/reactive_context.rs", "/dioxus/packages/core/src/render_error.rs", "/dioxus/packages/core/src/root_wrapper.rs", "/dioxus/packages/core/src/runtime.rs", "/dioxus/packages/core/src/scheduler.rs", "/dioxus/packages/core/src/scope_arena.rs", "/dioxus/packages/core/src/scope_context.rs", "/dioxus/packages/core/src/scopes.rs", "/dioxus/packages/core/src/suspense/component.rs", "/dioxus/packages/core/src/suspense/mod.rs", "/dioxus/packages/core/src/tasks.rs", "/dioxus/packages/core/src/virtual_dom.rs", "/dioxus/packages/core-macro/README.md", "/dioxus/packages/core-macro/docs/component.md", "/dioxus/packages/core-macro/docs/props.md", "/dioxus/packages/core-macro/docs/rsx.md", "/dioxus/packages/core-macro/src/component.rs", "/dioxus/packages/core-macro/src/lib.rs", "/dioxus/packages/core-macro/src/props/mod.rs", "/dioxus/packages/core-macro/src/utils.rs", "/dioxus/packages/core-types/src/bubbles.rs", "/dioxus/packages/core-types/src/bundled.rs", "/dioxus/packages/core-types/src/formatter.rs", "/dioxus/packages/core-types/src/hr_context.rs", "/dioxus/packages/core-types/src/lib.rs", "/dioxus/packages/devtools/src/lib.rs", "/dioxus/packages/devtools-types/src/lib.rs", "/dioxus/packages/dioxus-lib/README.md", "/dioxus/packages/dioxus-lib/src/lib.rs", "/dioxus/packages/document/build.rs", "/dioxus/packages/document/docs/eval.md", "/dioxus/packages/document/docs/head.md", "/dioxus/packages/document/src/document.rs", "/dioxus/packages/document/src/elements/link.rs", "/dioxus/packages/document/src/elements/meta.rs", "/dioxus/packages/document/src/elements/mod.rs", "/dioxus/packages/document/src/elements/script.rs", "/dioxus/packages/document/src/elements/style.rs", "/dioxus/packages/document/src/elements/stylesheet.rs", "/dioxus/packages/document/src/elements/title.rs", "/dioxus/packages/document/src/error.rs", "/dioxus/packages/document/src/eval.rs", "/dioxus/packages/document/src/js/head.js", "/dioxus/packages/document/src/lib.rs", "/dioxus/packages/document/./src/ts/eval.ts", "/dioxus/packages/document/./src/ts/head.ts", "/dioxus/packages/dx-wire-format/src/lib.rs", "/dioxus/packages/fullstack/README.md", "/dioxus/packages/fullstack/src/document/mod.rs", "/dioxus/packages/fullstack/src/hooks/mod.rs", "/dioxus/packages/fullstack/src/hooks/server_cached.rs", "/dioxus/packages/fullstack/src/hooks/server_future.rs", "/dioxus/packages/fullstack/src/html_storage/mod.rs", "/dioxus/packages/fullstack/src/lib.rs", "/dioxus/packages/generational-box/README.md", "/dioxus/packages/generational-box/src/entry.rs", "/dioxus/packages/generational-box/src/error.rs", "/dioxus/packages/generational-box/src/lib.rs", "/dioxus/packages/generational-box/src/references.rs", "/dioxus/packages/generational-box/src/sync.rs", "/dioxus/packages/generational-box/src/unsync.rs", "/dioxus/packages/history/src/lib.rs", "/dioxus/packages/history/src/memory.rs", "/dioxus/packages/hooks/README.md", "/dioxus/packages/hooks/docs/derived_state.md", "/dioxus/packages/hooks/docs/moving_state_around.md", "/dioxus/packages/hooks/docs/rules_of_hooks.md", "/dioxus/packages/hooks/docs/side_effects.md", "/dioxus/packages/hooks/docs/use_resource.md", "/dioxus/packages/hooks/src/lib.rs", "/dioxus/packages/hooks/src/use_callback.rs", "/dioxus/packages/hooks/src/use_context.rs", "/dioxus/packages/hooks/src/use_coroutine.rs", "/dioxus/packages/hooks/src/use_effect.rs", "/dioxus/packages/hooks/src/use_future.rs", "/dioxus/packages/hooks/src/use_hook_did_run.rs", "/dioxus/packages/hooks/src/use_memo.rs", "/dioxus/packages/hooks/src/use_on_destroy.rs", "/dioxus/packages/hooks/src/use_reactive.rs", "/dioxus/packages/hooks/src/use_resource.rs", "/dioxus/packages/hooks/src/use_root_context.rs", "/dioxus/packages/hooks/src/use_set_compare.rs", "/dioxus/packages/hooks/src/use_signal.rs", "/dioxus/packages/html/README.md", "/dioxus/packages/html/docs/common_event_handler_errors.md", "/dioxus/packages/html/docs/event_handlers.md", "/dioxus/packages/html/src/attribute_groups.rs", "/dioxus/packages/html/src/elements.rs", "/dioxus/packages/html/src/events/animation.rs", "/dioxus/packages/html/src/events/clipboard.rs", "/dioxus/packages/html/src/events/composition.rs", "/dioxus/packages/html/src/events/drag.rs", "/dioxus/packages/html/src/events/focus.rs", "/dioxus/packages/html/src/events/form.rs", "/dioxus/packages/html/src/events/image.rs", "/dioxus/packages/html/src/events/keyboard.rs", "/dioxus/packages/html/src/events/media.rs", "/dioxus/packages/html/src/events/mod.rs", "/dioxus/packages/html/src/events/mounted.rs", "/dioxus/packages/html/src/events/mouse.rs", "/dioxus/packages/html/src/events/pointer.rs", "/dioxus/packages/html/src/events/resize.rs", "/dioxus/packages/html/src/events/scroll.rs", "/dioxus/packages/html/src/events/selection.rs", "/dioxus/packages/html/src/events/toggle.rs", "/dioxus/packages/html/src/events/touch.rs", "/dioxus/packages/html/src/events/transition.rs", "/dioxus/packages/html/src/events/visible.rs", "/dioxus/packages/html/src/events/wheel.rs", "/dioxus/packages/html/src/file_data.rs", "/dioxus/packages/html/src/geometry.rs", "/dioxus/packages/html/src/input_data.rs", "/dioxus/packages/html/src/lib.rs", "/dioxus/packages/html/src/point_interaction.rs", "/dioxus/packages/html/src/render_template.rs", "/dioxus/packages/html-internal-macro/src/lib.rs", "/dioxus/packages/lazy-js-bundle/src/lib.rs", "/dioxus/packages/manganis/manganis/README.md", "/dioxus/packages/manganis/manganis/src/hash.rs", "/dioxus/packages/manganis/manganis/src/lib.rs", "/dioxus/packages/manganis/manganis/src/macro_helpers.rs", "/dioxus/packages/manganis/manganis-core/src/asset.rs", "/dioxus/packages/manganis/manganis-core/src/css.rs", "/dioxus/packages/manganis/manganis-core/src/folder.rs", "/dioxus/packages/manganis/manganis-core/src/hash.rs", "/dioxus/packages/manganis/manganis-core/src/images.rs", "/dioxus/packages/manganis/manganis-core/src/js.rs", "/dioxus/packages/manganis/manganis-core/src/lib.rs", "/dioxus/packages/manganis/manganis-core/src/linker.rs", "/dioxus/packages/manganis/manganis-core/src/options.rs", "/dioxus/packages/manganis/manganis-macro/README.md", "/dioxus/packages/manganis/manganis-macro/src/asset.rs", "/dioxus/packages/manganis/manganis-macro/src/lib.rs", "/dioxus/packages/manganis/manganis-macro/src/linker.rs", "/dioxus/packages/rsx/src/assign_dyn_ids.rs", "/dioxus/packages/rsx/src/attribute.rs", "/dioxus/packages/rsx/src/component.rs", "/dioxus/packages/rsx/src/diagnostics.rs", "/dioxus/packages/rsx/src/element.rs", "/dioxus/packages/rsx/src/expr_node.rs", "/dioxus/packages/rsx/src/forloop.rs", "/dioxus/packages/rsx/src/ifchain.rs", "/dioxus/packages/rsx/src/ifmt.rs", "/dioxus/packages/rsx/src/lib.rs", "/dioxus/packages/rsx/src/literal.rs", "/dioxus/packages/rsx/src/location.rs", "/dioxus/packages/rsx/src/node.rs", "/dioxus/packages/rsx/src/partial_closure.rs", "/dioxus/packages/rsx/src/raw_expr.rs", "/dioxus/packages/rsx/src/rsx_block.rs", "/dioxus/packages/rsx/src/rsx_call.rs", "/dioxus/packages/rsx/src/template_body.rs", "/dioxus/packages/rsx/src/text_node.rs", "/dioxus/packages/rsx/src/util.rs", "/dioxus/packages/rsx-hotreload/src/collect.rs", "/dioxus/packages/rsx-hotreload/src/diff.rs", "/dioxus/packages/rsx-hotreload/src/extensions.rs", "/dioxus/packages/rsx-hotreload/src/last_build_state.rs", "/dioxus/packages/rsx-hotreload/src/lib.rs", "/dioxus/packages/rsx-rosetta/README.md", "/dioxus/packages/rsx-rosetta/src/lib.rs", "/dioxus/packages/server-macro/src/lib.rs", "/dioxus/packages/signals/README.md", "/dioxus/packages/signals/docs/hoist/error.rs", "/dioxus/packages/signals/docs/hoist/fixed_list.rs", "/dioxus/packages/signals/docs/memo.md", "/dioxus/packages/signals/docs/signals.md", "/dioxus/packages/signals/src/copy_value.rs", "/dioxus/packages/signals/src/global/memo.rs", "/dioxus/packages/signals/src/global/mod.rs", "/dioxus/packages/signals/src/global/signal.rs", "/dioxus/packages/signals/src/impls.rs", "/dioxus/packages/signals/src/lib.rs", "/dioxus/packages/signals/src/map.rs", "/dioxus/packages/signals/src/memo.rs", "/dioxus/packages/signals/src/props.rs", "/dioxus/packages/signals/src/read.rs", "/dioxus/packages/signals/src/set_compare.rs", "/dioxus/packages/signals/src/signal.rs", "/dioxus/packages/signals/src/warnings.rs", "/dioxus/packages/signals/src/write.rs", "/dioxus/target/debug/build/dioxus-cli-90993e55e02b7cee/out/built.rs", ]; assert_eq!( answer.iter().map(PathBuf::from).collect::>(), info.files ); } }