Skip to content

Conversation

@afiffon
Copy link
Owner

@afiffon afiffon commented Oct 7, 2025

  • Add CLI info --show-quota
  • Remove test (samba requires too much setup for now :()

misc:

  • Remove unwrap_* methods in query/set cast types
  • Add some doc
  • Add Boolean::Into<bool>
  • Add macro for generating Resource casts

Summary by CodeRabbit

  • New Features

    • CLI option to display quota info alongside directory listings.
    • Human-readable quota sizes with "∞" for unlimited.
    • Quota queries can be built from a single SID or a list; directory quota queries return multiple entries and setting quotas accepts multiple items.
  • Documentation

    • Enhanced docs for info enums with safer accessors and variant metadata (type/name).

@afiffon afiffon linked an issue Oct 7, 2025 that may be closed by this pull request
@afiffon afiffon self-assigned this Oct 7, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 7, 2025

Walkthrough

Adds quota support across layers: new fscc::quota types, msg mapping to chained quota lists, Directory query/set API updated to use Vec, CLI flag to optionally display quota during traversal, conversion helpers and TryInto macro, and safer as_* accessors replacing unwrap_*.

Changes

Cohort / File(s) Summary
CLI quota flag & traversal
crates/smb-cli/src/info.rs
Adds public InfoCmd.show_quota; propagates via IterateParams; queries and displays quota for directories during iteration; removes display_func hook; adds helpers try_query_and_show_quota, display_quota_info; updates get_size_string formatting (u64::MAX → "∞").
FSCC quota module & types
crates/smb-fscc/src/lib.rs, crates/smb-fscc/src/quota.rs
Adds quota module and pub use quota::*; introduces FileQuotaInformation, FileGetQuotaInformationInner, and type FileGetQuotaInformation = ChainedItem<...> with binrw annotations; removes older public quota structs/type aliases from root.
MSG: info enum accessors & docs
crates/smb-msg/src/info/common.rs
Replaces unwrap_* with fallible as_* accessors returning Result; adds info_type() and name() methods; implements From<Content> -> enum variants; updates macro docs.
MSG: quota query/set mapping & constructors
crates/smb-msg/src/info/query.rs, crates/smb-msg/src/info/set.rs
Maps Quota to ChainedItemList<FileQuotaInformation> in query/set macros; adds QueryQuotaInfo::new and ::new_sid constructors; enforces non-empty content when present; tests updated accordingly.
Resource TryInto macro & fallible access
crates/smb/src/resource.rs
Adds make_resource_try_into! macro generating TryInto impls for File/Directory/Pipe with Error = (crate::Error, Self) tuple; removes previous specific impls; switches to as_security()?/as_filesystem()?.
Directory quota API changes
crates/smb/src/resource/directory.rs
query_quota_info now returns crate::Result<Vec<FileQuotaInformation>> via as_quota()?.into(); set_quota_info now accepts Vec<FileQuotaInformation> and converts to ChainedItemList before calling set.
DTYP bool conversion helper
crates/smb-dtyp/src/binrw_util/helpers.rs
Adds impl From<Boolean> for bool to convert wrapper Boolean into primitive bool.
Tests cleanup
crates/smb/tests/dialects.rs
Removes commented-out quota query block; no functional test behavior changed.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as InfoCmd (smb-cli)
  participant Iter as Iterator
  participant Dir as Directory (smb)
  participant Srv as SMB Server

  User->>CLI: run info (show_quota=true)
  CLI->>Iter: iterate path(s) with show_quota
  loop For each directory
    Iter->>Dir: query_quota_info(...)
    Dir->>Srv: FSCTL/QueryInfo (expects ChainedItemList<FileQuotaInformation>)
    Srv-->>Dir: chained quota response
    Dir-->>Iter: Vec<FileQuotaInformation> (as_quota()?.into())
    Note right of Iter: display_quota_info(...)
  end
  Iter-->>CLI: item info + quota (if any)
  CLI-->>User: output
Loading
sequenceDiagram
  autonumber
  participant Dir as Directory (smb)
  participant Msg as smb-msg
  participant Fscc as smb-fscc::quota
  participant Srv as SMB Server

  Dir->>Msg: build Query (ChainedItemList<FileQuotaInformation>)
  Msg->>Srv: send QueryInfo (Quota)
  Srv-->>Msg: chained quota list
  Msg-->>Dir: as_quota()?.into() -> Vec<FileQuotaInformation>

  Dir->>Fscc: ChainedItemList::from(Vec<FileQuotaInformation>)
  Dir->>Srv: SetInfo Quota with chained list
  Srv-->>Dir: status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I thump my paws on bytes so neat,
Chained quotas hop in tidy feet.
as_carrots, not unwrap_snacks—
safer trails on rabbit tracks.
A macro burrow, TryInto cheer,
We query, set, then disappear—
Infinity size? I twitch an ear. 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title highlights the bugfix for set/query FILE_QUOTA_INFORMATION which is indeed part of the changeset but omits the addition of the CLI --show-quota flag and other enhancements, so it only partially reflects the main scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 130-query-quota-information

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/smb-msg/src/info/common.rs (1)

72-79: Fix moved-self usage in as_* match

match self { … _ => … self.name() } uses self after it has been moved into the match, so this code will not compile. Bind the non-matching branch to a new identifier and call name() on it instead.

-                    pub fn [<as_ $info_type:lower>](self) -> Result<$content, $crate::SmbMsgError> {
-                        match self {
-                            $name::$info_type(data) => Ok(data),
-                            _ => Err($crate::SmbMsgError::UnexpectedContent {
-                                expected: stringify!($info_type),
-                                actual: self.name(),
-                            }),
-                        }
-                    }
+                    pub fn [<as_ $info_type:lower>](self) -> Result<$content, $crate::SmbMsgError> {
+                        match self {
+                            $name::$info_type(data) => Ok(data),
+                            value => Err($crate::SmbMsgError::UnexpectedContent {
+                                expected: stringify!($info_type),
+                                actual: value.name(),
+                            }),
+                        }
+                    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab9620d and f44e632.

📒 Files selected for processing (10)
  • crates/smb-cli/src/info.rs (6 hunks)
  • crates/smb-dtyp/src/binrw_util/helpers.rs (1 hunks)
  • crates/smb-fscc/src/lib.rs (2 hunks)
  • crates/smb-fscc/src/quota.rs (1 hunks)
  • crates/smb-msg/src/info/common.rs (3 hunks)
  • crates/smb-msg/src/info/query.rs (5 hunks)
  • crates/smb-msg/src/info/set.rs (2 hunks)
  • crates/smb/src/resource.rs (3 hunks)
  • crates/smb/src/resource/directory.rs (2 hunks)
  • crates/smb/tests/dialects.rs (0 hunks)
💤 Files with no reviewable changes (1)
  • crates/smb/tests/dialects.rs
🧰 Additional context used
🧬 Code graph analysis (4)
crates/smb-fscc/src/quota.rs (2)
crates/smb-fscc/src/chained_item.rs (1)
  • value (45-47)
crates/smb-dtyp/src/binrw_util/pos_marker.rs (1)
  • write_size (480-497)
crates/smb-msg/src/info/query.rs (2)
crates/smb/src/resource.rs (2)
  • new (719-723)
  • as_file (189-194)
crates/smb-fscc/src/chained_item.rs (1)
  • new (41-43)
crates/smb/src/resource/directory.rs (1)
crates/smb-fscc/src/chained_item.rs (4)
  • from (125-130)
  • from (162-164)
  • from (173-177)
  • from (222-224)
crates/smb-cli/src/info.rs (2)
crates/smb-msg/src/info/query.rs (1)
  • new (152-163)
crates/smb/src/resource/directory.rs (3)
  • new (27-34)
  • new (356-383)
  • new (474-487)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test (async)
  • GitHub Check: test (multi_threaded)
  • GitHub Check: test (single_threaded)
  • GitHub Check: build-msrv
🔇 Additional comments (14)
crates/smb-dtyp/src/binrw_util/helpers.rs (1)

128-132: LGTM! Clean bidirectional conversion for Boolean wrapper.

The From<Boolean> for bool implementation correctly provides ergonomic unwrapping of the Boolean newtype and automatically enables Into<bool> via the standard library's blanket implementation. This complements the existing From<bool> for Boolean conversion nicely.

crates/smb-msg/src/info/set.rs (1)

39-39: LGTM! Quota type mapping updated correctly.

The change from QueryQuotaInfo to ChainedItemList<FileQuotaInformation> aligns with the new quota API introduced in the smb-fscc::quota module. The validation logic at line 80 remains compatible with this change.

crates/smb-fscc/src/lib.rs (2)

18-18: LGTM! Import cleanup.

The removal of TakeSeekExt from the top-level imports is appropriate as it's likely used only in specific submodules (like quota.rs at line 2) where it's directly imported.


29-29: LGTM! Quota module properly integrated.

The new quota module is correctly declared as public and its items are re-exported, making the quota API available to consumers of this crate. This follows the standard Rust module organization pattern seen with other modules in this file.

Also applies to: 38-38

crates/smb-fscc/src/quota.rs (1)

32-45: LGTM! Quota information structures well-defined.

The FileGetQuotaInformationInner struct and FileGetQuotaInformation type alias follow the established pattern for chained items. The use of PosMarker for variable-length SID fields is appropriate, and the documentation correctly references the MS-FSCC specification.

crates/smb-cli/src/info.rs (6)

43-46: LGTM! Quota flag added to CLI.

The show_quota flag is properly integrated into the InfoCmd struct with appropriate defaults and documentation.


88-90: LGTM! Initial quota query integrated.

The quota information is queried for the root directory when show_quota is enabled, using the new helper function.


152-158: LGTM! Size formatting enhanced with infinity handling.

The addition of u64::MAX => "∞" is a nice UX improvement for displaying unlimited quotas. The existing size formatting logic remains intact.


164-164: LGTM! Params structure extended correctly.

The show_quota field is appropriately added to IterateParams for propagating the flag through the iteration logic.


230-234: Verify the recursion gating logic with show_quota.

Line 232 changes the early-return condition to params.recursive < RecursiveMode::List && !params.show_quota. This means:

  • If show_quota is true, the function will not early-return and will continue to process subdirectories even when recursive == RecursiveMode::NonRecursive
  • This couples quota display with directory traversal in a potentially unexpected way

Question: Is this the intended behavior? Should enabling show_quota force traversal of subdirectories when the user specified --recursive=non-recursive?

If this is intentional (e.g., to query quota on each subdirectory even in non-recursive mode), consider adding a comment explaining this behavior:

-    if params.recursive < RecursiveMode::List && !params.show_quota {
+    // Continue processing subdirectories if either:
+    // 1. Recursive mode is List (explicit recursion), OR
+    // 2. show_quota is enabled (to query quota on subdirectories)
+    if params.recursive < RecursiveMode::List && !params.show_quota {
         return None;
     }

Otherwise, if quota should only be shown for directories that are already being traversed:

     display_item_info(info, dir_path);
 
-    if params.recursive < RecursiveMode::List && !params.show_quota {
+    if params.recursive < RecursiveMode::List {
         return None;
     }

And move the quota query to only execute during recursive traversal.


285-293: LGTM! Quota query helper is well-structured.

The try_query_and_show_quota helper properly encapsulates quota querying with error handling, making the code more maintainable. The use of QueryQuotaInfo::new(false, true, vec![]) with an empty vector correctly requests all quotas as per the MS-SMB2 specification.

crates/smb-msg/src/info/query.rs (3)

148-176: LGTM! Constructor methods provide a clean API.

The two constructor methods new() and new_sid() provide clear, type-safe ways to build QueryQuotaInfo for the two different query modes specified in MS-SMB2 2.2.37.1. The documentation references are helpful, and the implementations correctly handle the mutual exclusivity of the two options.


239-239: LGTM! Quota type mapping updated correctly.

The change from QueryQuotaInfo to ChainedItemList<FileQuotaInformation> aligns with the new quota API in the smb-fscc::quota module. This makes the quota response data structure consistent with other chained information types in the SMB protocol.


384-385: LGTM! Accessor pattern updated correctly.

The change from unwrap_file() to as_file().unwrap() aligns with the PR objective to remove unwrap_* methods in favor of fallible as_* accessors. This pattern is more idiomatic Rust and provides better flexibility (e.g., allowing as_file()?.some_method() chains).

Also applies to: 417-418

- Add CLI `info --show-quota`
- Remove test (samba requires too much setup for now :()

misc:
- Remove `unwrap_*` methods in query/set cast types
- Add some doc
- Add `Boolean::Into<bool>`
- Add macro for generating `Resource` casts
@afiffon afiffon force-pushed the 130-query-quota-information branch from f44e632 to 15ffa96 Compare October 7, 2025 15:46
@afiffon afiffon force-pushed the main branch 2 times, most recently from bae3bdf to 84f9da7 Compare October 7, 2025 15:54
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/smb-msg/src/info/common.rs (1)

40-109: Excellent safety improvement!

Replacing the unwrap_* methods with as_* methods that return Result<Content, SmbMsgError> eliminates panic risks and provides better error handling. The addition of info_type(), name(), and From<Content> implementations enhances the API ergonomics.

The macro-generated code now:

  • Returns descriptive errors via SmbMsgError::UnexpectedContent instead of panicking
  • Provides introspection via info_type() and name()
  • Simplifies conversions with From implementations
♻️ Duplicate comments (5)
crates/smb-fscc/src/quota.rs (2)

15-17: Doc hint fix looks good

Reference to ChainedItem/ChainedItemList is now correct; the confusing “Inner” hint is gone.


19-29: Add logical validation for quota fields (optional but helpful)

Provide a validate() to catch quota_used/threshold exceeding quota_limit (treat u64::MAX as unlimited).

Example:

impl FileQuotaInformation {
    pub fn validate(&self) -> Result<(), &'static str> {
        if self.quota_limit != u64::MAX && self.quota_used > self.quota_limit {
            return Err("quota_used exceeds quota_limit");
        }
        if self.quota_limit != u64::MAX && self.quota_threshold > self.quota_limit {
            return Err("quota_threshold exceeds quota_limit");
        }
        Ok(())
    }
}
crates/smb-msg/src/info/set.rs (1)

5-5: Check if NullByte is already re-exported via common:: (avoid redundant import)*

If common::* exports NullByte, the explicit NullByte can be dropped; otherwise keep as-is.

#!/bin/bash
# Show where NullByte is defined and whether it's re-exported from common.
rg -nP --type=rust 'struct\s+NullByte|enum\s+NullByte|type\s+NullByte' crates/smb-msg/src/info -C2
rg -nP --type=rust 'pub\s+use.*NullByte' crates/smb-msg/src/info -C2
crates/smb-cli/src/info.rs (2)

254-266: Simplify conversion and avoid re-binding name

Minor cleanup: use a temporary resource binding and a single match.

-    let dir = dir_result.unwrap();
-
-    let dir: Directory = match dir.try_into() {
+    let resource = dir_result.unwrap();
+    let dir: Directory = match resource.try_into() {
         Ok(dir) => dir,
         Err(e) => {
             log::warn!(
                 "Failed to convert resource to directory {}: {}",
                 path_of_subdir,
                 e.0
             );
             return None;
         }
     };

131-145: Tighten skip logic and message for “no limits” quotas

Message says “no limit” but condition checks both limit and threshold. Make the log precise.

-fn display_quota_info(info: &Vec<smb::FileQuotaInformation>) {
+fn display_quota_info(info: &[smb::FileQuotaInformation]) {
     for quota in info {
-        if quota.quota_limit == u64::MAX && quota.quota_threshold == u64::MAX {
-            log::trace!("Skipping quota for SID {} with no limit", quota.sid);
+        if quota.quota_limit == u64::MAX && quota.quota_threshold == u64::MAX {
+            log::trace!("Skipping quota for SID {} (no limits set)", quota.sid);
             continue; // No quota set
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f44e632 and 15ffa96.

📒 Files selected for processing (10)
  • crates/smb-cli/src/info.rs (6 hunks)
  • crates/smb-dtyp/src/binrw_util/helpers.rs (1 hunks)
  • crates/smb-fscc/src/lib.rs (2 hunks)
  • crates/smb-fscc/src/quota.rs (1 hunks)
  • crates/smb-msg/src/info/common.rs (3 hunks)
  • crates/smb-msg/src/info/query.rs (5 hunks)
  • crates/smb-msg/src/info/set.rs (2 hunks)
  • crates/smb/src/resource.rs (3 hunks)
  • crates/smb/src/resource/directory.rs (2 hunks)
  • crates/smb/tests/dialects.rs (0 hunks)
💤 Files with no reviewable changes (1)
  • crates/smb/tests/dialects.rs
🧰 Additional context used
🧬 Code graph analysis (4)
crates/smb-cli/src/info.rs (1)
crates/smb-msg/src/info/query.rs (1)
  • new (152-163)
crates/smb-msg/src/info/query.rs (1)
crates/smb/src/resource.rs (1)
  • as_file (189-194)
crates/smb-fscc/src/quota.rs (1)
crates/smb-dtyp/src/binrw_util/pos_marker.rs (1)
  • write_size (480-497)
crates/smb/src/resource/directory.rs (1)
crates/smb-fscc/src/chained_item.rs (4)
  • from (125-130)
  • from (162-164)
  • from (173-177)
  • from (222-224)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (multi_threaded)
  • GitHub Check: test (single_threaded)
  • GitHub Check: test (async)
🔇 Additional comments (16)
crates/smb-dtyp/src/binrw_util/helpers.rs (1)

128-132: LGTM! Bidirectional conversion is now complete.

The implementation correctly provides conversion from Boolean to bool, complementing the existing From<bool> for Boolean. This enables idiomatic usage of the wrapper type with automatic Into<bool> support via Rust's blanket implementation.

crates/smb/src/resource.rs (2)

449-450: Good switch to typed accessor

Using as_security()? avoids panics and matches other as_* uses.


576-577: Good typed cast

as_filesystem()? is the safe cast counterpart; consistent with the new pattern.

crates/smb-msg/src/info/set.rs (1)

39-40: Quota payload type change is correct

Using ChainedItemList matches the on‑wire chained list format; aligns with the new FSCC quota types.

crates/smb-fscc/src/lib.rs (1)

29-39: LGTM: quota module export

Adding pub mod quota and pub use quota::* cleanly surfaces the new types.

crates/smb-cli/src/info.rs (6)

43-46: CLI flag addition looks good

show_quota is optional and defaults to false; clear help text.


88-90: Good: conditional quota query

Running quota query only when requested avoids extra IO.


152-158: Size formatting improvement approved

u64::MAX as “∞” and humanized sizes are helpful.


230-233: Traversal gating reads well

When not listing recursively, still open subdirs when show_quota is true. Intentional and clear.


268-283: Good: query quota per subdir when requested

Closes handle when not recursing; avoids leaks.


285-294: Graceful error handling

try_query_and_show_quota logs and continues; no hard fail on unsupported servers.

crates/smb-msg/src/info/query.rs (3)

134-134: Nice improvement! Addresses the past review comment.

The use of is_some_and is cleaner and more idiomatic than the previous verbose condition or the suggested map_or alternative. This method is specifically designed for this use case.


148-176: LGTM! Well-documented constructors.

The two constructors properly implement the two query options from the MS-SMB2 spec (2.2.37.1):

  • Option #1: List of FileGetQuotaInformation structs
  • Option #2: Single SID

The mutual exclusivity is correctly enforced by the assertion at line 143, and the boolean conversions using .into() are appropriate.


239-239: Significant but correct API change.

The change from QueryQuotaInfo to ChainedItemList<FileQuotaInformation> aligns with the broader quota refactoring in this PR. The tests at lines 384-385 and 417-418 have been updated to use the new as_file() accessor, confirming the migration is consistent across the codebase.

crates/smb/src/resource/directory.rs (2)

275-298: LGTM! Clean API with correct conversions.

The method signature changes improve clarity:

  • Input: QueryQuotaInfo provides structured query parameters
  • Output: Vec<FileQuotaInformation> returns the quota data directly

The implementation correctly:

  • Extracts boolean flags from the info parameter (lines 290-291)
  • Uses the safe as_quota()? accessor instead of unwrapping
  • Converts ChainedItemList<FileQuotaInformation> to Vec<FileQuotaInformation> via the From implementation (validated in relevant code snippets)

300-312: LGTM! Correct conversion and clean API.

The simplified signature accepting Vec<FileQuotaInformation> directly is more intuitive. The conversion to ChainedItemList at line 304 is valid per the From<Vec<T>> implementation in chained_item.rs (lines 172-176 in relevant snippets).

Comment on lines +31 to +33
/// See [`FileGetQuotaInformation`]; use [`FileGetQuotaInformationInner::into`] to convert.
#[binrw::binrw]
#[derive(Debug)]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Clarify conversion wording

“use FileGetQuotaInformationInner::into” -> say “use .into() to wrap into ChainedItem” for clarity.

-/// See [`FileGetQuotaInformation`]; use [`FileGetQuotaInformationInner::into`] to convert.
+/// See [`FileGetQuotaInformation`]; use `.into()` to wrap into `ChainedItem<FileGetQuotaInformationInner>`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// See [`FileGetQuotaInformation`]; use [`FileGetQuotaInformationInner::into`] to convert.
#[binrw::binrw]
#[derive(Debug)]
/// See [`FileGetQuotaInformation`]; use `.into()` to wrap into `ChainedItem<FileGetQuotaInformationInner>`.
#[binrw::binrw]
#[derive(Debug)]
🤖 Prompt for AI Agents
In crates/smb-fscc/src/quota.rs around lines 31 to 33, update the doc comment
that currently reads “use FileGetQuotaInformationInner::into” to instead say
“use .into() to wrap into ChainedItem<FileGetQuotaInformationInner>” so it
clearly instructs callers to call .into() to produce a
ChainedItem<FileGetQuotaInformationInner>; keep the surrounding text and
references unchanged.

Comment on lines +226 to 248
/// Generates TryInto implementations for Resource enum variants.
macro_rules! make_resource_try_into {
(
$($t:ident,)+
) => {
$(

fn try_into(self) -> Result<File, Self::Error> {
match self {
Resource::File(f) => Ok(f),
_ => Err(Error::InvalidArgument("Not a file".into())),
}
}
}
impl TryInto<$t> for Resource {
type Error = (crate::Error, Self);

impl TryInto<Directory> for Resource {
type Error = crate::Error;

fn try_into(self) -> Result<Directory, Self::Error> {
fn try_into(self) -> Result<$t, Self::Error> {
match self {
Resource::Directory(d) => Ok(d),
_ => Err(Error::InvalidArgument("Not a directory".into())),
Resource::$t(f) => Ok(f),
x => Err((Error::InvalidArgument(format!("Not a {}", stringify!($t))), x)),
}
}
}
)+
};
}

make_resource_try_into!(File, Directory, Pipe,);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Prefer TryFrom for idiomatic conversions (lets std provide TryInto automatically)

Implement TryFrom for each variant instead of TryInto; callers keep using .try_into(), but you get the blanket impl and a more idiomatic API.

Apply this diff:

-/// Generates TryInto implementations for Resource enum variants.
-macro_rules! make_resource_try_into {
+/// Generates TryFrom<Resource> implementations for enum variants and uses the blanket TryInto.
+macro_rules! make_resource_try_from {
     (
         $($t:ident,)+
     ) => {
         $(
-
-impl TryInto<$t> for Resource {
-    type Error = (crate::Error, Self);
-
-    fn try_into(self) -> Result<$t, Self::Error> {
-        match self {
-            Resource::$t(f) => Ok(f),
-            x => Err((Error::InvalidArgument(format!("Not a {}", stringify!($t))), x)),
-        }
-    }
-}
+impl TryFrom<Resource> for $t {
+    type Error = (crate::Error, Resource);
+    fn try_from(value: Resource) -> Result<$t, Self::Error> {
+        match value {
+            Resource::$t(v) => Ok(v),
+            other => Err((Error::InvalidArgument(format!("Not a {}", stringify!($t))), other)),
+        }
+    }
+}
         )+
     };
 }
 
-make_resource_try_into!(File, Directory, Pipe,);
+make_resource_try_from!(File, Directory, Pipe,);

Also applies to: 247-247

@afiffon afiffon merged commit 567dc35 into main Oct 7, 2025
5 of 9 checks passed
@afiffon afiffon deleted the 130-query-quota-information branch October 10, 2025 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Query Quota information

2 participants