aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md30
-rw-r--r--Cargo.toml1
-rw-r--r--docs/example-pages/examples.json14
-rw-r--r--examples/example-lazy-resources/Cargo.lock76
-rw-r--r--examples/example-lazy-resources/Cargo.toml8
-rw-r--r--examples/example-lazy-resources/page.toml10
-rw-r--r--examples/example-lazy-resources/src/main.rs92
-rw-r--r--examples/test-examples.toml10
-rw-r--r--mingling/src/example_docs.rs108
-rw-r--r--mingling_core/src/asset.rs9
-rw-r--r--mingling_core/src/asset/lazy_resource.rs141
-rw-r--r--mingling_core/src/lib.rs1
-rw-r--r--mling/src/cli.rs15
-rw-r--r--mling/src/pkg_mgr/installer.rs0
-rw-r--r--mling/src/pkg_mgr/mod.rs3
-rw-r--r--mling/src/proj_mgr/metadata.rs8
16 files changed, 517 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95db724..bc74d21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,36 @@ program.with_setup(BasicProgramSetup);
3. **\[core\]** Added `verbose`, `quiet`, `debug`, `color`, and `progress` fields to `ProgramStdoutSetting`, and `dry_run`, `force`, `interactive`, and `assume_yes` fields to `ProgramUserContext`. These fields are annotated as conventions only, meaning the framework does not enforce any particular behavior — it is up to the application to read and act on them.
+4. **\[core\]** Added `LazyRes<T>` for lazy resource initialization. Resources wrapped in `LazyRes<T>` are only initialized when first accessed via `get_ref()` or `get_mut()`, rather than immediately when added to the program. This is useful for resources that are expensive to initialize and may not always be needed.
+
+```rust
+use std::collections::BTreeMap;
+use mingling::{LazyInit, LazyRes, prelude::*};
+
+#[derive(Default, Clone)]
+pub struct ResLargeData {
+ pub data: BTreeMap<String, String>,
+}
+
+fn init_res_large_data() -> ResLargeData {
+ // Expensive initialization here
+ ResLargeData { data: BTreeMap::new() }
+}
+
+fn main() {
+ let mut program = ThisProgram::new();
+ program.with_resource(ResLargeData::lazy_init(init_res_large_data));
+ // ...
+}
+
+// Injected as &mut LazyRes<T> instead of &T
+#[renderer]
+fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) {
+ let res = res.get_ref(); // Initialization happens here
+ // use res...
+}
+```
+
#### **BREAKING CHANGES** (API CHANGES):
1. **\[core\]** Changed the signature of `ProgramSetup::setup` from `fn setup(&mut self, program: &mut Program<C>) -> S` to `fn setup(self, program: &mut Program<C>)`, consuming `self` instead of taking a mutable reference. Correspondingly, `Program::with_setup` now accepts `S` by value (`&mut self, setup: S`) instead of by mutable reference (`&mut self, setup: &mut S`).
diff --git a/Cargo.toml b/Cargo.toml
index 45afe35..051bde7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,7 @@ exclude = [
"examples/example-help",
"examples/example-hook",
"examples/example-implicit-dispatcher",
+ "examples/example-lazy-resources",
"examples/example-panic-unwind",
"examples/example-repl-basic",
"examples/example-resources",
diff --git a/docs/example-pages/examples.json b/docs/example-pages/examples.json
index 4db968c..9022066 100644
--- a/docs/example-pages/examples.json
+++ b/docs/example-pages/examples.json
@@ -205,6 +205,20 @@
]
},
{
+ "id": "example-lazy-resources",
+ "name": "Lazy Resources",
+ "icon": "💤️",
+ "category": "advanced",
+ "desc": "Example Lazy Resources\n",
+ "tags": [
+ "LazyRes<Res>"
+ ],
+ "files": [
+ "src/main.rs",
+ "Cargo.toml"
+ ]
+ },
+ {
"id": "example-panic-unwind",
"name": "Panic Unwind",
"icon": "💥",
diff --git a/examples/example-lazy-resources/Cargo.lock b/examples/example-lazy-resources/Cargo.lock
new file mode 100644
index 0000000..eb7d9b3
--- /dev/null
+++ b/examples/example-lazy-resources/Cargo.lock
@@ -0,0 +1,76 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "example-lazy-resources"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+]
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/examples/example-lazy-resources/Cargo.toml b/examples/example-lazy-resources/Cargo.toml
new file mode 100644
index 0000000..1f47f8e
--- /dev/null
+++ b/examples/example-lazy-resources/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "example-lazy-resources"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies.mingling]
+path = "../../mingling"
+features = []
diff --git a/examples/example-lazy-resources/page.toml b/examples/example-lazy-resources/page.toml
new file mode 100644
index 0000000..d2c740f
--- /dev/null
+++ b/examples/example-lazy-resources/page.toml
@@ -0,0 +1,10 @@
+[example]
+id = "example-lazy-resources"
+name = "Lazy Resources"
+icon = "💤️"
+category = "advanced"
+desc = """
+Example Lazy Resources
+"""
+tags = ["LazyRes<Res>"]
+files = ["src/main.rs", "Cargo.toml"]
diff --git a/examples/example-lazy-resources/src/main.rs b/examples/example-lazy-resources/src/main.rs
new file mode 100644
index 0000000..3533ae2
--- /dev/null
+++ b/examples/example-lazy-resources/src/main.rs
@@ -0,0 +1,92 @@
+//! Example Lazy Resources
+//!
+//! > This example demonstrates how to use `LazyRes` for lazy resource initialization.
+//!
+//! Run:
+//! ```bash
+//! cargo run --manifest-path examples/example-lazy-resources/Cargo.toml --quiet none
+//!
+//! cargo run --manifest-path examples/example-lazy-resources/Cargo.toml --quiet show
+//! ```
+//!
+//! Output:
+//! ```plaintext
+//! None
+//!
+//! Initialized
+//! foo: bar
+//! rust: lang
+//! baz: qux
+//! hello: world
+//! key: value
+//! ```
+
+use std::collections::BTreeMap;
+
+use mingling::{LazyInit, LazyRes, prelude::*};
+
+type Key = String;
+type Value = String;
+
+// Define a resource that requires time-consuming initialization
+#[derive(Default, Clone)]
+pub struct ResLargeData {
+ pub data: BTreeMap<Key, Value>,
+}
+
+fn init_res_large_data() -> ResLargeData {
+ // Perform time-consuming initialization here
+ let mut data = BTreeMap::new();
+ data.insert("foo".to_string(), "bar".to_string());
+ data.insert("baz".to_string(), "qux".to_string());
+ data.insert("hello".to_string(), "world".to_string());
+ data.insert("rust".to_string(), "lang".to_string());
+ data.insert("key".to_string(), "value".to_string());
+
+ // Print to indicate initialization is complete
+ println!("Initialized");
+ ResLargeData { data }
+}
+
+dispatcher!("show", CMDShow => EntryShow);
+dispatcher!("none", CMDNone => EntryNone);
+
+pack!(ResultShow = BTreeMap<Key, Value>);
+
+fn main() {
+ let mut program = ThisProgram::new();
+
+ // --------- IMPORTANT ---------
+ // _ Use lazy_init to create LazyRes<ResLargeData>
+ // /
+ // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+ program.with_resource(ResLargeData::lazy_init(init_res_large_data));
+ // --------- IMPORTANT ---------
+
+ program.with_dispatchers((CMDShow, CMDNone));
+ program.exec_and_exit();
+}
+
+// Inject LazyRes instead of a normal resource
+// __________________________ Must use &mut because `get_ref` and `get_mut`
+// / both require mutable borrow
+// | _____________________ Use LazyRes<ResLargeData>
+// | / instead of ResLargeData
+#[renderer] // vvvv vvvvvvvvvvvvvvvvvvvvv
+fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) {
+ // _______ Initialization happens here
+ // /
+ // vvvvvvv
+ let res = res.get_ref();
+ for (key, value) in &res.data {
+ r_println!("{}: {}", key, value);
+ }
+}
+
+// When not using LazyRes<ResLargeData>, it will not be initialized
+#[renderer]
+fn render_entry_none(_args: EntryNone) {
+ r_println!("None");
+}
+
+gen_program!();
diff --git a/examples/test-examples.toml b/examples/test-examples.toml
index 6f45048..8d2cf0d 100644
--- a/examples/test-examples.toml
+++ b/examples/test-examples.toml
@@ -1,3 +1,13 @@
+[[test.example-lazy-resources]]
+command = "none"
+expect.exit-code = 0
+expect.result = "None"
+
+[[test.example-lazy-resources]]
+command = "show"
+expect.exit-code = 0
+expect.result = "Initialized\nbaz: qux\nfoo: bar\nhello: world\nkey: value\nrust: lang"
+
[[test.example-basic]]
command = "greet"
expect.exit-code = 0
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index 3755553..f14aa30 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -1412,6 +1412,114 @@ pub mod example_hook {}
/// gen_program!();
/// ```
pub mod example_implicit_dispatcher {}
+/// Example Lazy Resources
+///
+/// > This example demonstrates how to use `LazyRes` for lazy resource initialization.
+///
+/// Run:
+/// ```bash
+/// cargo run --manifest-path examples/example-lazy-resources/Cargo.toml --quiet none
+///
+/// cargo run --manifest-path examples/example-lazy-resources/Cargo.toml --quiet show
+/// ```
+///
+/// Output:
+/// ```plaintext
+/// None
+///
+/// Initialized
+/// foo: bar
+/// rust: lang
+/// baz: qux
+/// hello: world
+/// key: value
+/// ```
+///
+/// Source code (./Cargo.toml)
+/// ```toml
+/// [package]
+/// name = "example-lazy-resources"
+/// version = "0.1.0"
+/// edition = "2024"
+///
+/// [dependencies.mingling]
+/// path = "../../mingling"
+/// features = []
+/// ```
+///
+/// Source code (./src/main.rs)
+/// ```ignore
+/// use std::collections::BTreeMap;
+///
+/// use mingling::{LazyInit, LazyRes, prelude::*};
+///
+/// type Key = String;
+/// type Value = String;
+///
+/// // Define a resource that requires time-consuming initialization
+/// #[derive(Default, Clone)]
+/// pub struct ResLargeData {
+/// pub data: BTreeMap<Key, Value>,
+/// }
+///
+/// fn init_res_large_data() -> ResLargeData {
+/// // Perform time-consuming initialization here
+/// let mut data = BTreeMap::new();
+/// data.insert("foo".to_string(), "bar".to_string());
+/// data.insert("baz".to_string(), "qux".to_string());
+/// data.insert("hello".to_string(), "world".to_string());
+/// data.insert("rust".to_string(), "lang".to_string());
+/// data.insert("key".to_string(), "value".to_string());
+///
+/// // Print to indicate initialization is complete
+/// println!("Initialized");
+/// ResLargeData { data }
+/// }
+///
+/// dispatcher!("show", CMDShow => EntryShow);
+/// dispatcher!("none", CMDNone => EntryNone);
+///
+/// pack!(ResultShow = BTreeMap<Key, Value>);
+///
+/// fn main() {
+/// let mut program = ThisProgram::new();
+///
+/// // --------- IMPORTANT ---------
+/// // _ Use lazy_init to create LazyRes<ResLargeData>
+/// // /
+/// // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+/// program.with_resource(ResLargeData::lazy_init(init_res_large_data));
+/// // --------- IMPORTANT ---------
+///
+/// program.with_dispatchers((CMDShow, CMDNone));
+/// program.exec_and_exit();
+/// }
+///
+/// // Inject LazyRes instead of a normal resource
+/// // __________________________ Must use &mut because `get_ref` and `get_mut`
+/// // / both require mutable borrow
+/// // | _____________________ Use LazyRes<ResLargeData>
+/// // | / instead of ResLargeData
+/// #[renderer] // vvvv vvvvvvvvvvvvvvvvvvvvv
+/// fn render_entry_show(_args: EntryShow, res: &mut LazyRes<ResLargeData>) {
+/// // _______ Initialization happens here
+/// // /
+/// // vvvvvvv
+/// let res = res.get_ref();
+/// for (key, value) in &res.data {
+/// r_println!("{}: {}", key, value);
+/// }
+/// }
+///
+/// // When not using LazyRes<ResLargeData>, it will not be initialized
+/// #[renderer]
+/// fn render_entry_none(_args: EntryNone) {
+/// r_println!("None");
+/// }
+///
+/// gen_program!();
+/// ```
+pub mod example_lazy_resources {}
/// Example Panic Unwind
///
/// > This example introduces how to catch Panic in the Mingling program loop
diff --git a/mingling_core/src/asset.rs b/mingling_core/src/asset.rs
index e7945ce..b1fd617 100644
--- a/mingling_core/src/asset.rs
+++ b/mingling_core/src/asset.rs
@@ -11,10 +11,13 @@ pub mod enum_tag;
pub mod global_resource;
#[doc(hidden)]
-pub mod node;
+pub mod help;
#[doc(hidden)]
-pub mod renderer;
+pub mod lazy_resource;
#[doc(hidden)]
-pub mod help;
+pub mod node;
+
+#[doc(hidden)]
+pub mod renderer;
diff --git a/mingling_core/src/asset/lazy_resource.rs b/mingling_core/src/asset/lazy_resource.rs
new file mode 100644
index 0000000..41f8a34
--- /dev/null
+++ b/mingling_core/src/asset/lazy_resource.rs
@@ -0,0 +1,141 @@
+use crate::{ProgramCollect, ResourceMarker, this};
+
+/// A lazily initialized resource that only creates its value on first access via a given initializer function.
+///
+/// `LazyRes<T>` wraps an `Option<T>` and an initializer function, supporting thread-safe lazy loading.
+/// Initialization is triggered by calls to `get_ref()`, `get_mut()`, or `get_clone()`.
+pub struct LazyRes<T: Default + Send + Sync + Clone> {
+ /// The initializer function, called on first access to produce the inner value.
+ init_fn: Box<dyn FnMut() -> T + Send + Sync>,
+ /// Stores the initialized value; `None` means not yet initialized.
+ inner: Option<T>,
+}
+
+impl<T: Default + Send + Sync + Clone> Default for LazyRes<T> {
+ /// Creates an uninitialized `LazyRes<T>` whose initializer returns `T::default()`.
+ fn default() -> Self {
+ Self {
+ inner: None,
+ init_fn: Box::new(|| T::default()),
+ }
+ }
+}
+
+impl<T: Default + Send + Sync + Clone + 'static> LazyRes<T> {
+ /// Creates a new lazily initialized resource with a custom initializer function.
+ ///
+ /// # Parameters
+ /// - `f`: The initializer function called on first access, returning a value of type `T`.
+ ///
+ /// # Returns
+ /// Returns an uninitialized `LazyRes<T>`.
+ #[must_use]
+ pub fn new(f: impl FnMut() -> T + Send + Sync + 'static) -> Self {
+ Self {
+ inner: None,
+ init_fn: Box::new(f),
+ }
+ }
+
+ /// Returns an immutable reference to the inner value, calling the initializer if necessary.
+ ///
+ /// # Returns
+ /// An immutable reference to the inner value `T`.
+ pub fn get_ref(&mut self) -> &T {
+ if self.inner.is_none() {
+ self.inner = Some((self.init_fn)());
+ }
+ self.inner.as_ref().unwrap()
+ }
+
+ /// Returns a mutable reference to the inner value, calling the initializer if necessary.
+ ///
+ /// # Returns
+ /// A mutable reference to the inner value `T`.
+ pub fn get_mut(&mut self) -> &mut T {
+ if self.inner.is_none() {
+ self.inner = Some((self.init_fn)());
+ }
+ self.inner.as_mut().unwrap()
+ }
+
+ /// Resets the lazy resource by taking and returning the inner value; on next access, re-initialization occurs.
+ ///
+ /// # Returns
+ /// Returns the previously initialized value if any, otherwise `None`.
+ pub fn reset(&mut self) -> Option<T> {
+ self.inner.take()
+ }
+
+ /// Returns a clone of the inner value, calling the initializer if necessary.
+ ///
+ /// # Returns
+ /// A clone of type `T`.
+ pub fn get_clone(&mut self) -> T {
+ self.get_ref().clone()
+ }
+}
+
+impl<T: Default + Send + Sync + Clone + 'static> From<T> for LazyRes<T> {
+ /// Creates a `LazyRes<T>` from an existing value (already initialized), with the initializer set to `T::default()`.
+ fn from(value: T) -> Self {
+ Self {
+ inner: Some(value),
+ init_fn: Box::new(|| T::default()),
+ }
+ }
+}
+
+impl<T: Default + Send + Sync + Clone + 'static> LazyRes<T> {
+ /// Creates a lazily initialized resource using `T::default()` as the initializer.
+ pub fn lazy_default() -> Self {
+ Self::default()
+ }
+
+ /// Creates a lazily initialized resource with a custom initializer function.
+ ///
+ /// Same as `LazyRes::new`.
+ pub fn lazy_init(f: impl FnMut() -> T + Send + Sync + 'static) -> Self {
+ Self::new(f)
+ }
+}
+
+/// Provides convenience methods for types implementing `Default + Send + Sync + Clone + 'static`,
+/// allowing them to easily create a corresponding `LazyRes<T>`.
+pub trait LazyInit: Default + Send + Sync + Clone + 'static {
+ /// Creates a lazily initialized resource for this type using `Default` as the initializer.
+ fn lazy_default() -> LazyRes<Self> {
+ LazyRes::default()
+ }
+
+ /// Creates a lazily initialized resource for this type with a custom initializer function.
+ fn lazy_init(f: impl FnMut() -> Self + Send + Sync + 'static) -> LazyRes<Self> {
+ LazyRes::new(f)
+ }
+}
+
+impl<T: Default + Send + Sync + Clone + 'static> LazyInit for T {}
+
+impl<T: Default + Send + Sync + Clone + 'static> ResourceMarker for LazyRes<T> {
+ /// Clones the lazy resource. The cloned resource retains any initialized value, but the initializer is reset to `T::default()`.
+ fn res_clone(&self) -> Self {
+ Self {
+ inner: self.inner.clone(),
+ // The original initializer is not preserved on clone
+ init_fn: Box::new(|| T::default()),
+ }
+ }
+
+ /// Returns a default lazy resource (uninitialized, using `T::default()` as the initializer).
+ fn res_default() -> Self {
+ Self::default()
+ }
+
+ /// Modifies the current lazy resource via the `this` context provided by `C`.
+ fn modify<C>(f: impl FnOnce(&mut Self))
+ where
+ C: ProgramCollect<Enum = C> + 'static,
+ {
+ this::<C>().modify_res(f);
+ }
+}
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 6e1e90c..ddb5446 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -30,6 +30,7 @@ pub use crate::asset::dispatcher::*;
pub use crate::asset::enum_tag::*;
pub use crate::asset::global_resource::*;
pub use crate::asset::help::*;
+pub use crate::asset::lazy_resource::*;
pub use crate::asset::node::*;
pub use crate::asset::renderer::*;
diff --git a/mling/src/cli.rs b/mling/src/cli.rs
index 21f7220..6a4c7d8 100644
--- a/mling/src/cli.rs
+++ b/mling/src/cli.rs
@@ -116,6 +116,13 @@ fn standard_output_setup(program: &mut Program<ThisProgram>) {
}
fn resolve_manifest_path(provided: Option<String>) -> PathBuf {
+ let p = ThisProgram::this();
+ let disable_error_output =
+ // --no-error
+ !p.stdout_setting.error_output ||
+ // or --quiet/--silence
+ p.stdout_setting.quiet;
+
if let Some(path) = provided {
let p = PathBuf::from_str(&path).unwrap();
if p.is_dir() {
@@ -123,7 +130,9 @@ fn resolve_manifest_path(provided: Option<String>) -> PathBuf {
if candidate.exists() {
return candidate;
}
- eprintln_cargo!("`{}` is not a crate root", p.display());
+ if !disable_error_output {
+ eprintln_cargo!("`{}` is not a crate root", p.display());
+ }
exit(1);
}
return p;
@@ -137,7 +146,9 @@ fn resolve_manifest_path(provided: Option<String>) -> PathBuf {
}
if !dir.pop() {
// Reached filesystem root without finding Cargo.toml
- eprintln_cargo!("`{}` is not a crate root", current_dir().unwrap().display());
+ if !disable_error_output {
+ eprintln_cargo!("`{}` is not a crate root", current_dir().unwrap().display());
+ }
exit(1);
}
}
diff --git a/mling/src/pkg_mgr/installer.rs b/mling/src/pkg_mgr/installer.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mling/src/pkg_mgr/installer.rs
diff --git a/mling/src/pkg_mgr/mod.rs b/mling/src/pkg_mgr/mod.rs
index d03e1d8..030529e 100644
--- a/mling/src/pkg_mgr/mod.rs
+++ b/mling/src/pkg_mgr/mod.rs
@@ -4,6 +4,9 @@ use mingling::{
macros::{dispatcher, program_setup},
};
+mod installer;
+pub use installer::*;
+
dispatcher!("install");
dispatcher!("ls.namespace", CMDListNamespace => EntryListNamespace);
dispatcher!("rm.namespace", CMDRemoveNamespace => EntryRemoveNamespace);
diff --git a/mling/src/proj_mgr/metadata.rs b/mling/src/proj_mgr/metadata.rs
index 84da69f..1ba24e1 100644
--- a/mling/src/proj_mgr/metadata.rs
+++ b/mling/src/proj_mgr/metadata.rs
@@ -16,10 +16,10 @@ pub fn read_metadata(cargo_toml: &PathBuf) -> Result<CargoLockFile, std::io::Err
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
- return Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- format!("cargo metadata failed: {}", stderr),
- ));
+ return Err(std::io::Error::other(format!(
+ "cargo metadata failed: {}",
+ stderr
+ )));
}
let lock_file: CargoLockFile = serde_json::from_slice(&output.stdout)