-
Notifications
You must be signed in to change notification settings - Fork 192
Rust 🦀 #1275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Rust 🦀 #1275
Conversation
WalkthroughThis pull request adds comprehensive Rust SDK support to an API specification code generator. It includes a new PHP Language class implementing Rust-specific code generation logic, over 30 Twig templates for scaffolding Rust projects (client, models, services, error handling, workflows), updates to CI/CD workflows to support Rust builds and tests, PHP example generator modifications, and Rust test infrastructure. The implementation enables automatic generation of production-ready Rust SDKs from API specifications. Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
update: djlint config for rust, readme.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (15)
templates/rust/.github/workflows/publish.yml.twig (1)
16-17: Consider consistency in Rust toolchain versions.This workflow uses
@stablewhile the validation workflow uses@1.83.0. This inconsistency could lead to publishing with a different Rust version than what was tested in CI.Consider either:
- Using the same pinned version (
@1.83.0) for consistency, or- Documenting why stable is preferred for publishing
🔎 Proposed fix to align with CI validation version
- name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@1.83.0example.php (1)
270-276: Consider setting Rust-specific configuration.The Rust SDK generation uses only default configuration. Based on the
Rust.phplanguage class, there's asetCratePackage()method available. Consider whether a specific crate package name should be set, similar to how other SDKs configure their package names (e.g., Dart usessetPackageName('dart_appwrite')).🔎 Example configuration with crate package name
// Rust if (!$requestedSdk || $requestedSdk === 'rust') { - $sdk = new SDK(new Rust(), new Swagger2($spec)); + $rust = new Rust(); + $rust->setCratePackage('appwrite'); + $sdk = new SDK($rust, new Swagger2($spec)); configureSDK($sdk); $sdk->generate(__DIR__ . '/examples/rust'); }templates/rust/tests/tests.rs (2)
102-105: Clarify duplicate test calls.Lines 102-103 and 104-105 each call the same test functions twice (
test_general_uploadandtest_large_upload). If this is intentional to test idempotency or retry behavior, consider adding a comment. Otherwise, these might be unintentional duplicates.test_general_upload(client, string_in_array).await?; - test_general_upload(client, string_in_array).await?; test_large_upload(client, string_in_array).await?; - test_large_upload(client, string_in_array).await?;
206-269: Consider adding assertions for query tests.The query tests only print outputs but don't verify correctness. While this might be sufficient for integration testing against a mock API that validates the output format, consider whether some basic assertions would improve test reliability.
templates/rust/CHANGELOG.md.twig (1)
44-50: Ensure dependency versions match Cargo.toml.The dependency versions listed in the changelog should match those in
Cargo.toml.twig. When updating dependency versions in Cargo.toml, remember to update this changelog template as well.templates/rust/src/id.rs.twig (1)
16-18: Consider graceful error handling instead of panic.The
.expect("Time went backwards")will panic if system time moves backwards (e.g., NTP correction, VM snapshot restore). For a production SDK, consider returning aResultor using a fallback strategy.🔎 Proposed alternatives
Option 1: Return Result from the function
- pub fn unique_with_padding(padding: usize) -> String { + pub fn unique_with_padding(padding: usize) -> Result<String, std::time::SystemTimeError> { let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); + .duration_since(UNIX_EPOCH)?;Option 2: Use a fallback to maintain the current API
let now = SystemTime::now() .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); + .unwrap_or_else(|_| std::time::Duration::from_secs(0));templates/rust/src/permission.rs.twig (1)
15-38: Update misleading documentation comments.The doc comments say "for any user" but all methods accept a
roleparameter that determines the specific role/user. The comments should reflect that these methods create permissions for the specified role.🔎 Proposed documentation fix
- /// Read permission for any user + /// Read permission for the specified role pub fn read(role: impl std::fmt::Display) -> Self { Self::new(format!("read(\"{}\")", role)) } - /// Write permission for any user + /// Write permission for the specified role pub fn write(role: impl std::fmt::Display) -> Self { Self::new(format!("write(\"{}\")", role)) } - /// Create permission for any user + /// Create permission for the specified role pub fn create(role: impl std::fmt::Display) -> Self { Self::new(format!("create(\"{}\")", role)) } - /// Update permission for any user + /// Update permission for the specified role pub fn update(role: impl std::fmt::Display) -> Self { Self::new(format!("update(\"{}\")", role)) } - /// Delete permission for any user + /// Delete permission for the specified role pub fn delete(role: impl std::fmt::Display) -> Self { Self::new(format!("delete(\"{}\")", role)) }templates/rust/src/models/model.rs.twig (1)
51-77: Tests rely onDefaulttrait that may not be meaningful for all models.The test module assumes all field types implement
Default. For models with required fields of custom types (e.g., nested models),Default::default()may produce invalid/empty data that could cause issues during serialization roundtrips if the server rejects empty required fields.Consider adding a comment noting this limitation, or generating more meaningful test data for required fields.
templates/rust/src/input_file.rs.twig (1)
163-168:is_empty()returnsfalsefor path-based files without checking actual size.For
InputFileSource::Path, returningfalseunconditionally could be misleading if the file is actually empty (0 bytes). Consider usingsize_sync()or documenting this behavior.🔎 Suggested improvement
pub fn is_empty(&self) -> bool { match &self.source { InputFileSource::Bytes { data } => data.is_empty(), - InputFileSource::Path { .. } => false, + InputFileSource::Path { path } => { + std::fs::metadata(path).map(|m| m.len() == 0).unwrap_or(true) + } } }templates/rust/src/client.rs.twig (3)
124-136: Consider returningResultinstead of panicking on invalid endpoint.Panicking in
set_endpointfor invalid URLs could cause unexpected crashes in user code. AResultreturn type or a non-builder method that validates would be more robust.🔎 Alternative approach
- pub fn set_endpoint<S: Into<String>>(&self, endpoint: S) -> Self { + pub fn set_endpoint<S: Into<String>>(&self, endpoint: S) -> Result<Self, crate::error::{{ spec.title | caseUcfirst }}Error> { let endpoint = endpoint.into(); if !endpoint.starts_with("http://") && !endpoint.starts_with("https://") { - panic!("Invalid endpoint URL: {}. Endpoint must start with http:// or https://", endpoint); + return Err(crate::error::{{ spec.title | caseUcfirst }}Error::new( + 0, + format!("Invalid endpoint URL: {}. Endpoint must start with http:// or https://", endpoint), + None, + String::new(), + )); } // ... rest of method - self.clone() + Ok(self.clone()) }
216-234: Silent failure inadd_headercould hide configuration errors.When header name or value parsing fails, the method silently proceeds without adding the header. Consider logging a warning or returning a
Resultto help users debug configuration issues.
375-479:call_locationcreates a new HTTP client per invocation.Lines 387-392 build a new
reqwest::Clientfor eachcall_locationcall. While this is needed for the no-redirect policy, client creation has overhead. Consider caching a no-redirect client inClientStateif this method is called frequently.src/SDK/Language/Rust.php (1)
539-552: Unused parameters flagged by static analysis are likely intentional for interface consistency.The
$spec,$namespace,$genericparameters ingetPropertyType,getReturnType, andhasGenericTypeare currently unused but may be required by the parent class interface or reserved for future use. If intentional, consider adding@SuppressWarningsor a brief comment.Also applies to: 643-667, 674-695
templates/rust/src/query.rs.twig (2)
251-257: Unnecessary clone inDisplayimplementation.
to_value(self)takes ownership, butDisplay::fmtonly has&self. The current approach clones the entire Query. Consider derivingSerializeforQuerydirectly or implementing a method that serializes from&self.🔎 Alternative: derive Serialize directly
#[derive(Debug, Clone, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct Query { method: String, #[serde(skip_serializing_if = "Option::is_none")] attribute: Option<String>, #[serde(skip_serializing_if = "Vec::is_empty")] values: Vec<Value>, } impl std::fmt::Display for Query { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let json_str = serde_json::to_string(self) .unwrap_or_else(|_| String::new()); write!(f, "{}", json_str) } }
210-232:orandandmethods require pre-serialized JSON strings.The API requires users to serialize Query objects to strings first, then pass them to
or/and. This is somewhat awkward. Consider also acceptingVec<Query>directly.🔎 Additional overload suggestion
/// Combine queries with OR (accepts Query objects directly) pub fn or_queries(queries: impl IntoIterator<Item = Query>) -> Self { let values: Vec<Value> = queries.into_iter().map(|q| q.to_value()).collect(); Self::new("or".to_string(), None, values) }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (32)
.github/workflows/sdk-build-validation.yml.github/workflows/tests.ymlexample.phppyproject.tomlsrc/SDK/Language/Rust.phptemplates/rust/.github/workflows/autoclose.ymltemplates/rust/.github/workflows/publish.yml.twigtemplates/rust/.github/workflows/stale.ymltemplates/rust/.gitignoretemplates/rust/CHANGELOG.md.twigtemplates/rust/Cargo.toml.twigtemplates/rust/LICENSE.twigtemplates/rust/README.md.twigtemplates/rust/examples/basic_usage.rs.twigtemplates/rust/src/client.rs.twigtemplates/rust/src/enums/enum.rs.twigtemplates/rust/src/enums/mod.rs.twigtemplates/rust/src/error.rs.twigtemplates/rust/src/id.rs.twigtemplates/rust/src/input_file.rs.twigtemplates/rust/src/lib.rs.twigtemplates/rust/src/models/mod.rs.twigtemplates/rust/src/models/model.rs.twigtemplates/rust/src/models/request_model.rs.twigtemplates/rust/src/permission.rs.twigtemplates/rust/src/query.rs.twigtemplates/rust/src/role.rs.twigtemplates/rust/src/services/mod.rs.twigtemplates/rust/src/services/service.rs.twigtemplates/rust/tests/tests.rstests/Rust183Test.phptests/languages/rust/test.sh
🧰 Additional context used
🧬 Code graph analysis (1)
example.php (3)
src/SDK/Language.php (1)
Language(5-295)src/SDK/Language/Rust.php (1)
Rust(8-696)src/Spec/Swagger2.php (1)
Swagger2(7-646)
🪛 PHPMD (2.15.0)
src/SDK/Language/Rust.php
274-274: Avoid unused parameters such as '$spec'. (undefined)
(UnusedFormalParameter)
408-408: Avoid unused parameters such as '$lang'. (undefined)
(UnusedFormalParameter)
539-539: Avoid unused parameters such as '$generic'. (undefined)
(UnusedFormalParameter)
645-645: Avoid unused parameters such as '$spec'. (undefined)
(UnusedFormalParameter)
646-646: Avoid unused parameters such as '$namespace'. (undefined)
(UnusedFormalParameter)
647-647: Avoid unused parameters such as '$generic'. (undefined)
(UnusedFormalParameter)
🪛 Shellcheck (0.11.0)
tests/languages/rust/test.sh
[warning] 4-4: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🔇 Additional comments (50)
templates/rust/LICENSE.twig (1)
1-1: LGTM!The template correctly uses the
rawfilter to output unescaped license content.templates/rust/.gitignore (1)
1-24: LGTM!The .gitignore patterns are comprehensive and follow Rust ecosystem conventions. The exclusion of Cargo.lock is appropriate for library SDKs.
templates/rust/README.md.twig (1)
1-45: LGTM!The README template is well-structured with appropriate badge URLs, installation instructions, and conditional rendering for optional sections. The use of default values for
cratePackageensures robustness..github/workflows/tests.yml (1)
46-46: LGTM!The addition of Rust183 to the SDK matrix is consistent with the PR's objective to add Rust SDK support.
templates/rust/.github/workflows/stale.yml (1)
1-9: LGTM!The workflow correctly delegates to a reusable stale workflow with an appropriate daily schedule.
pyproject.toml (1)
6-9: LGTM!The additions to the djlint ignore list are well-justified with clear comments explaining the Rust-specific false positives (generics and references).
templates/rust/.github/workflows/autoclose.yml (1)
1-12: LGTM!The workflow correctly uses
pull_request_targetto access secrets and delegates to a trusted reusable workflow. The condition appropriately allows PRs from thedevbranch..github/workflows/sdk-build-validation.yml (3)
61-62: LGTM! Rust SDK added to the matrix.The addition of Rust as a server-side SDK is correctly configured and follows the same pattern as other SDKs in the matrix.
203-206: LGTM! Rust build commands are appropriate.The build and test commands follow Rust best practices:
cargo build --releaseensures the code compiles in release modecargo test --libruns library tests
146-148: Rust 1.83.0 version is correctly specified and aligns with project requirements.Verification confirms that Rust 1.83.0 is a stable version released on November 28, 2024, and matches the
rust-version = "1.83"specification inCargo.toml. The workflow's pinning to this specific patch version is appropriate for deterministic builds.templates/rust/.github/workflows/publish.yml.twig (2)
19-20: LGTM! Tests run before publishing.Running tests before publishing is a good practice to ensure code quality.
22-23: Verify CARGO_REGISTRY_TOKEN secret is configured.The workflow requires the
CARGO_REGISTRY_TOKENsecret to publish to crates.io. Ensure this secret is properly configured in the repository settings before the first release.example.php (2)
24-24: LGTM! Rust import added.The import follows the same pattern as other language imports.
281-283: LGTM! Enhanced error handling with Throwable.Catching
Throwablein addition toExceptionprovides better error coverage for PHP 7+ (catches both exceptions and errors). This is a good defensive programming practice.tests/Rust183Test.php (3)
7-10: LGTM! Test configuration is appropriate.The test class configuration correctly sets up the Rust SDK test parameters with appropriate naming and platform settings.
15-15: Ensure Docker image version consistency.The test uses
rust:1.83Docker image, which should align with:
- The rust-version in
Cargo.toml.twig(1.83)- The toolchain in CI workflows (1.83.0)
Verify these versions are consistent across the codebase.
14-15: The paths referenced are correct. Thetests/sdks/rust/directory is generated at test runtime by the SDK generation code inBase.php::testHTTPSuccess(), not pre-existing in the repository. Thetests/languages/rust/test.shscript exists and is properly referenced. This pattern is consistent across all language tests in the codebase.Likely an incorrect or invalid review comment.
templates/rust/Cargo.toml.twig (2)
1-18: LGTM! Package metadata is well-configured.The package metadata section correctly uses template variables and follows Rust packaging best practices. The rust-version of 1.83 aligns with the CI toolchain version.
39-44: LGTM! Conditional test binary configuration.The conditional inclusion of the test binary when
sdk.test == "true"is a good approach that keeps the published crate clean while supporting testing during development.templates/rust/tests/tests.rs (1)
6-22: LGTM! Main test orchestrator is well-structured.The async main function properly orchestrates all test functions in sequence, providing clear output and proper error propagation.
templates/rust/CHANGELOG.md.twig (1)
1-23: LGTM! Changelog follows best practices.The changelog template follows the Keep a Changelog format and provides comprehensive documentation of the initial release, including all features and capabilities.
templates/rust/examples/basic_usage.rs.twig (4)
10-20: LGTM! Client initialization example is clear and well-documented.The example demonstrates proper client initialization with appropriate placeholder values and clear comments guiding users to replace them.
24-41: LGTM! User creation example demonstrates proper error handling.The example shows both success and error cases with informative output, teaching users how to handle the SDK's error types correctly.
59-88: LGTM! Conditional service examples are well-structured.The conditional inclusion of database service examples based on
spec.servicesensures the example remains relevant for different API specifications.
127-143: Excellent error handling demonstration.The example explicitly demonstrates error handling with invalid credentials, showing users what to expect when API calls fail. This is valuable for learning the SDK's error patterns.
templates/rust/src/enums/mod.rs.twig (1)
1-6: LGTM!The module aggregator correctly generates public module declarations and re-exports for all enums. The pattern follows Rust conventions.
templates/rust/src/id.rs.twig (2)
46-118: LGTM!The test suite is comprehensive and covers length validation, uniqueness, hex format, custom IDs, padding behavior, and edge cases.
33-33: fastrand dependency is properly declared in Cargo.toml.The
fastrand = "2.0"dependency is already included in the Cargo.toml template dependencies section, so no action is needed.templates/rust/src/permission.rs.twig (1)
58-91: LGTM!Test coverage is solid and validates the permission string formatting for all builder methods.
templates/rust/src/lib.rs.twig (1)
1-62: LGTM!The library facade follows Rust conventions with:
- Clear module organization
- Idiomatic re-exports of commonly used types
- Type alias for SDK Result type
- SDK metadata as public constants
- Comprehensive documentation with usage example
templates/rust/src/services/mod.rs.twig (2)
24-33: LGTM!The initialization order is correct: services are instantiated with references to
client(lines 28-30) beforeclientis moved into the struct (line 31). This ensures each service has access to the client configuration during construction.
10-14: LGTM!The Service trait provides a clean abstraction for accessing the underlying client from any service implementation.
templates/rust/src/models/request_model.rs.twig (3)
1-23: LGTM!The request model struct follows Rust best practices:
- Proper serde attributes for JSON serialization
skip_serializing_iffor optional fields produces clean JSON- Field name transformation handles various casing conventions
- Conditional
Defaultderive for test convenience
25-49: LGTM!The accessor pattern is idiomatic:
- Fluent setters for optional fields (builder pattern)
- Reference getters for both required and optional fields
- Consistent naming convention
51-77: LGTM!Tests validate struct creation, accessor methods, and JSON serialization round-trip.
templates/rust/src/role.rs.twig (3)
1-66: LGTM!The Role builder implementation is excellent:
- Private constructor ensures controlled construction
- Generic
Into<String>parameters provide flexibility- Optional parameters handled idiomatically with
Option<&str>- Consistent string formatting for all role types
68-90: LGTM!The trait implementations provide ergonomic conversions:
Displayfor string renderingFrom<Role>for owned string extractionFrom<&str>andFrom<String>for flexible role creation
92-155: LGTM!Comprehensive test coverage validates all constructors, optional parameters, and conversions.
templates/rust/src/enums/enum.rs.twig (2)
4-4: Note: Copy derive restricts enum variants to simple types.The
Copyderive on Line 4 means all enum variants must beCopy, which prevents adding fields to variants later. This is appropriate for simple value enums (like status codes or flags) but would need to be removed if variants require associated data.Given this template generates API enums from specifications, the restriction is likely intentional and acceptable.
14-30: LGTM!The
as_str()method andDisplayimplementation provide idiomatic string conversion for enum variants, with proper serde attribute mapping for serialization.templates/rust/src/models/mod.rs.twig (1)
1-24: LGTM!The module structure is well-organized with proper re-exports for convenient access. The
Modeltrait withSerialize + Deserialize + Clone + Debugbounds is appropriate for SDK data models, and the blanket implementations for all generated types ensure consistency.templates/rust/src/models/model.rs.twig (1)
1-49: LGTM on the model generation template.The struct definition with serde attributes, optional field handling with
skip_serializing_if, and builder-style setters for optional fields follow idiomatic Rust patterns. The getter methods returning references are appropriate for the use case.templates/rust/src/services/service.rs.twig (2)
26-34: LGTM on service construction.The service pattern with
new(client: &Client)that clones the client andclient()accessor is clean and follows the SDK's arc-swap architecture for mutable client state.
35-141: Well-structured method generation with proper handling of various parameter types.The template correctly:
- Orders required parameters before optional ones (Lines 52-66)
- Uses
Option<&str>for optionalimpl Into<String>types (Line 61)- Handles query, body, and header parameters appropriately
- Routes to correct client methods based on method type (file upload, webAuth, location, standard)
templates/rust/src/error.rs.twig (1)
1-78: LGTM on error handling design.The error type with
thiserror::Errorderive, status code classification methods (is_client_error,is_server_error), andFromimplementations for common error types provide a solid foundation for SDK error handling.templates/rust/src/input_file.rs.twig (1)
1-161: LGTM on InputFile and ChunkedReader implementation.The dual-source design (Path vs Bytes), async/sync method pairs, and chunked reading with proper seek support are well-implemented. The
Fromtrait implementations provide convenient conversion ergonomics.Also applies to: 171-294
templates/rust/src/client.rs.twig (1)
59-112: LGTM on core client architecture.The
ArcSwappattern for thread-safe mutable configuration, snapshot-based request execution, and the separation of concerns between single/chunked uploads are well-designed. Response handling correctly distinguishes JSON vs non-JSON content types.Also applies to: 332-373, 566-631, 818-874
src/SDK/Language/Rust.php (2)
284-289: Fragile string matching for collection attributes.Relying on description text like
"Collection attributes"or"List of attributes"to determine type is brittle. If the API spec descriptions change, this logic will break silently.Consider whether there's a more reliable way to identify these types (e.g., schema properties, custom annotations).
1-97: LGTM on the Rust language backend implementation.The class provides comprehensive Rust code generation support with:
- Complete keyword list and raw identifier overrides
- Well-structured file scaffolding
- Type mapping with proper handling of arrays, enums, and models
- Useful Twig filters for rustdoc comments, type resolution, and DX improvements (impl Into patterns)
Also applies to: 139-267, 312-468, 470-531, 554-608, 610-641
templates/rust/src/query.rs.twig (1)
1-208: LGTM on the Query builder implementation.Comprehensive coverage of query operations (comparison, sorting, pagination, geospatial) with ergonomic generic bounds (
impl Into<String>,impl Into<Value>). The test suite thoroughly validates serialization and edge cases.Also applies to: 234-377
| /** | ||
| * @return array | ||
| */ | ||
| public function getIdentifierOverrides(): array | ||
| { | ||
| return [ | ||
| "type" => "r#type", | ||
| "match" => "r#match", | ||
| "ref" => "r#ref", | ||
| "move" => "r#move", | ||
| "static" => "r#static", | ||
| "const" => "r#const", | ||
| "struct" => "r#struct", | ||
| "enum" => "r#enum", | ||
| "trait" => "r#trait", | ||
| "impl" => "r#impl", | ||
| "fn" => "r#fn", | ||
| "let" => "r#let", | ||
| "mut" => "r#mut", | ||
| "use" => "r#use", | ||
| "pub" => "r#pub", | ||
| "crate" => "r#crate", | ||
| "mod" => "r#mod", | ||
| "super" => "r#super", | ||
| "self" => "r#self", | ||
| "where" => "r#where", | ||
| "async" => "r#async", | ||
| "await" => "r#await", | ||
| "loop" => "r#loop", | ||
| "while" => "r#while", | ||
| "for" => "r#for", | ||
| "if" => "r#if", | ||
| "else" => "r#else", | ||
| "match" => "r#match", | ||
| "return" => "r#return", | ||
| "break" => "r#break", | ||
| "continue" => "r#continue", | ||
| ]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate key "match" in getIdentifierOverrides().
The key "match" appears at both Line 106 and Line 132. While both map to "r#match" so there's no functional issue, the duplication is unnecessary and could cause confusion during maintenance.
🔎 Proposed fix
return [
"type" => "r#type",
- "match" => "r#match",
"ref" => "r#ref",
"move" => "r#move",
// ... other entries ...
"match" => "r#match", // Keep only this one
// ...
];📝 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.
| /** | |
| * @return array | |
| */ | |
| public function getIdentifierOverrides(): array | |
| { | |
| return [ | |
| "type" => "r#type", | |
| "match" => "r#match", | |
| "ref" => "r#ref", | |
| "move" => "r#move", | |
| "static" => "r#static", | |
| "const" => "r#const", | |
| "struct" => "r#struct", | |
| "enum" => "r#enum", | |
| "trait" => "r#trait", | |
| "impl" => "r#impl", | |
| "fn" => "r#fn", | |
| "let" => "r#let", | |
| "mut" => "r#mut", | |
| "use" => "r#use", | |
| "pub" => "r#pub", | |
| "crate" => "r#crate", | |
| "mod" => "r#mod", | |
| "super" => "r#super", | |
| "self" => "r#self", | |
| "where" => "r#where", | |
| "async" => "r#async", | |
| "await" => "r#await", | |
| "loop" => "r#loop", | |
| "while" => "r#while", | |
| "for" => "r#for", | |
| "if" => "r#if", | |
| "else" => "r#else", | |
| "match" => "r#match", | |
| "return" => "r#return", | |
| "break" => "r#break", | |
| "continue" => "r#continue", | |
| ]; | |
| } | |
| /** | |
| * @return array | |
| */ | |
| public function getIdentifierOverrides(): array | |
| { | |
| return [ | |
| "type" => "r#type", | |
| "ref" => "r#ref", | |
| "move" => "r#move", | |
| "static" => "r#static", | |
| "const" => "r#const", | |
| "struct" => "r#struct", | |
| "enum" => "r#enum", | |
| "trait" => "r#trait", | |
| "impl" => "r#impl", | |
| "fn" => "r#fn", | |
| "let" => "r#let", | |
| "mut" => "r#mut", | |
| "use" => "r#use", | |
| "pub" => "r#pub", | |
| "crate" => "r#crate", | |
| "mod" => "r#mod", | |
| "super" => "r#super", | |
| "self" => "r#self", | |
| "where" => "r#where", | |
| "async" => "r#async", | |
| "await" => "r#await", | |
| "loop" => "r#loop", | |
| "while" => "r#while", | |
| "for" => "r#for", | |
| "if" => "r#if", | |
| "else" => "r#else", | |
| "match" => "r#match", | |
| "return" => "r#return", | |
| "break" => "r#break", | |
| "continue" => "r#continue", | |
| ]; | |
| } |
🤖 Prompt for AI Agents
In src/SDK/Language/Rust.php around lines 99 to 137, the "match" key is
duplicated in the returned array (appearing at lines ~106 and ~132); remove the
redundant entry (keep a single "match" => "r#match") so the array contains
unique keys and update surrounding formatting if needed.
| [dependencies] | ||
| serde = { version = "1.0", features = ["derive"] } | ||
| serde_json = "1.0" | ||
| reqwest = { version = "0.12", features = ["json", "multipart", "stream"] } | ||
| tokio = { version = "1.0", features = ["full"] } | ||
| url = "2.4" | ||
| mime = "0.3" | ||
| fastrand = "2.0" | ||
| thiserror = "1.0" | ||
| bytes = "1.0" | ||
| arc-swap = "1.7" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
latest versions reqwest tokio serde arc-swap rust crates 2025
💡 Result:
As of Dec 28, 2025 — latest published versions:
- reqwest = 0.12.28. [1]
- tokio = 1.48.0. [2]
- serde = 1.0.228. [3]
- arc-swap = 1.8.0. [4]
Sources:
[1] reqwest docs.rs (latest).
[2] tokio docs.rs (latest).
[3] serde release list / crate pages (v1.0.228).
[4] arc-swap release (1.8.0) on docs.rs / crate trackers.
Update all dependencies to their current versions.
The dependency versions are significantly outdated:
reqwest: 0.12 → 0.12.28tokio: 1.0 → 1.48.0 (critical: 47 minor versions behind)serde: 1.0 → 1.0.228arc-swap: 1.7 → 1.8.0
The tokio version is particularly concerning, as it's missing significant feature releases, security patches, and performance improvements. Update all dependencies to their latest versions.
🤖 Prompt for AI Agents
In templates/rust/Cargo.toml.twig around lines 20–30, the dependency versions
are outdated; update all listed crates to their current published versions (at
minimum: reqwest = "0.12.28", tokio = "1.48.0" keeping the ["full"] feature,
serde = "1.0.228", arc-swap = "1.8.0") and bump serde_json, url, mime, fastrand,
thiserror, bytes to their latest compatible releases; ensure feature flags
(e.g., tokio "full", reqwest "json","multipart","stream", serde "derive") are
retained and run cargo update / cargo check to verify compatibility and resolve
any required minor adjustments in the Cargo.toml.
| }, | ||
| } | ||
|
|
||
| println!("Invalid endpoint URL: htp://cloud.appwrite.io/v1"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in error message URL.
The URL contains a typo: "htp://" should be "http://".
🔎 Proposed fix
- println!("Invalid endpoint URL: htp://cloud.appwrite.io/v1");
+ println!("Invalid endpoint URL: http://cloud.appwrite.io/v1");📝 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.
| println!("Invalid endpoint URL: htp://cloud.appwrite.io/v1"); | |
| println!("Invalid endpoint URL: http://cloud.appwrite.io/v1"); |
🤖 Prompt for AI Agents
In templates/rust/tests/tests.rs around line 134, the printed error message
contains a typo in the URL scheme ("htp://"). Update the string literal to use
the correct scheme "http://" so the message reads "Invalid endpoint URL:
http://cloud.appwrite.io/v1".
| #!/bin/sh | ||
| mkdir -p /tmp/rust-sdk | ||
| cp -Rf /app/tests/sdks/rust/* /tmp/rust-sdk/ | ||
| cd /tmp/rust-sdk |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for directory change.
If the cd command fails, subsequent cargo commands would execute in the wrong directory, potentially causing confusing failures.
🔎 Proposed fix
-cd /tmp/rust-sdk
+cd /tmp/rust-sdk || exit 1📝 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.
| cd /tmp/rust-sdk | |
| cd /tmp/rust-sdk || exit 1 |
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 4-4: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🤖 Prompt for AI Agents
In tests/languages/rust/test.sh around line 4, the script does a bare `cd
/tmp/rust-sdk` without checking for failure; update the line to check the exit
status and abort on failure (e.g., use a conditional or short-circuit to print
an error and exit non‑zero) so subsequent cargo commands do not run in the wrong
directory.
What does this PR do?
Adds Rust SDK support 🦀
Some notable arch related information -
Uses
arc-swapto maintain proper mutability of Client like how other SDKs manage. Its usually auto-handled for others but this needs to be explicitly managed. Usecase is not frequent but always a possibility where you want to change something on a client, add headers, etc. This allows us to redefine client and the service with new instances. Its not cheap but definitely not expensive as well since this is not a normal thing to change/add/update headers or client itself too frequently.Uses
tokio, the obvious choice andreqwestfor multipart.Test Plan
Manual, E2Es.
Related PRs and Issues
Have you read the Contributing Guidelines on issues?
Yes.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.