From 2b538cc88696825a205f223fa2ab46641a943312 Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Mon, 31 Mar 2025 12:25:18 +0200 Subject: [PATCH 1/3] Better error type --- src/rust/client_gen.rs | 57 +++++++++++++++++++++++++++++++++++++++--- src/rust/error_gen.rs | 7 +++++- src/toml/cargo.rs | 7 +++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/rust/client_gen.rs b/src/rust/client_gen.rs index 69c20ff..0e1fae9 100644 --- a/src/rust/client_gen.rs +++ b/src/rust/client_gen.rs @@ -17,7 +17,7 @@ use crate::rust::lib_gen::{Module, ModuleDef, ModuleName}; use crate::rust::model_gen::RefCache; use crate::rust::printer::*; use crate::rust::types::{ - ref_or_box_schema_type, ref_or_schema_type, DataType, RustPrinter, RustResult, + ref_or_box_schema_type, ref_or_schema_type, DataType, ModelType, RustPrinter, RustResult, }; use crate::{Error, Result}; use convert_case::{Case, Casing}; @@ -672,18 +672,69 @@ fn render_errors(method_name: &str, error_kind: &ErrorKind, errors: &MethodError .reduce(|acc, e| acc + e) .unwrap_or_else(unit); + let display_cases = errors + .codes + .iter() + .map(|(code, model)| { + line( + unit() + + name.clone() + + "::Error" + + code.to_string() + + "(body) => write!(f, \"{}\", " + + render_error_body_to_string(model) + + "),", + ) + }) + .reduce(|acc, e| acc + e) + .unwrap_or_else(unit); + #[rustfmt::skip] let res = unit() + line(unit() + "#[derive(Debug)]") + - line(unit() + "pub enum " + name + " {") + + line(unit() + "pub enum " + name.clone() + " {") + indented( code_cases ) + - line(unit() + "}"); + line(unit() + "}") + + line(unit() + "impl std::fmt::Display for " + name.clone() + " {") + + indented( + line(unit() + "fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {") + + indented( + if errors.codes.len() > 0 { + line(unit() + "match self {") + + indented(display_cases) + + line(unit() + "}") + } else { line(unit() + indented(unit() + "write!(f, \"" + name + "\")")) } + ) + + line("}") + ) + + line("}"); Ok(res) } +fn render_error_body_to_string(typ: &DataType) -> RustPrinter { + match typ { + DataType::Model(ModelType { name }) if name == "ErrorBody" => unit() + r#"&body.error"#, + DataType::Model(ModelType { name }) if name == "ErrorsBody" => { + unit() + r#"body.errors.clone().join(", ")"# + } + DataType::Model(ModelType { name }) if name == "WorkerServiceErrorsBody" => { + unit() + + "match &body { WorkerServiceErrorsBody::Messages(" + + rust_name("crate::model", "ErrorsBody") + + " { errors }) => { errors.join(\", \") }, WorkerServiceErrorsBody::Validation(" + + rust_name("crate::model", "ErrorsBody") + + " { errors }) => { errors.join(\", \") }}" + } + DataType::Model(ModelType { name }) if name == "GolemErrorBody" => { + unit() + r#"format!("{:?}", body.golem_error)"# + } + _ => unit() + r#"format!("{body:?}")"#, + } +} + fn async_annotation() -> RustPrinter { unit() + "#[" + rust_name("async_trait", "async_trait") + "]" } diff --git a/src/rust/error_gen.rs b/src/rust/error_gen.rs index 087d73f..54fde76 100644 --- a/src/rust/error_gen.rs +++ b/src/rust/error_gen.rs @@ -19,12 +19,17 @@ pub fn error_gen() -> Module { let code = indoc! { r#" use bytes::Bytes; - #[derive(Debug)] + #[derive(Debug, thiserror::Error)] pub enum Error { + #[error("{0}")] Item(T), + #[error("Client error: {0}")] Reqwest(reqwest::Error), + #[error("Invalid header value: {0}")] ReqwestHeader(reqwest::header::InvalidHeaderValue), + #[error("Deserialization error: {0}")] Serde(serde_json::Error), + #[error("Unexpected response - status {code}, data: {body}", body = "String::from_utf8_lossy(data.as_ref())")] Unexpected { code: u16, data: Bytes, diff --git a/src/toml/cargo.rs b/src/toml/cargo.rs index b5b9e74..0948ccc 100644 --- a/src/toml/cargo.rs +++ b/src/toml/cargo.rs @@ -29,15 +29,16 @@ pub fn gen(name: &str, version: &str) -> String { NewLine + "[dependencies]" + NewLine + r#"async-trait = "^0.1""# + NewLine + - r#"bytes = "^1.5""# + NewLine + + r#"bytes = "^1.10""# + NewLine + r#"chrono = { version = "^0.4", features = ["serde"] }"# + NewLine + r#"futures-core = "^0.3""# + NewLine + r#"http = "^1.0""# + NewLine + - r#"reqwest = { version = "^0.11", features = ["gzip", "json", "multipart", "stream"] }"# + NewLine + + r#"reqwest = { version = "^0.12", features = ["gzip", "json", "multipart", "stream"] }"# + NewLine + r#"serde = { version = "^1.0", features = ["derive"] }"# + NewLine + r#"serde_json = "^1.0""# + NewLine + + r#"thiserror = "^2"# + NewLine + r#"tracing = "^0.1""# + NewLine + - r#"uuid = { version = "^1.6", features = ["serde"] }"# + NewLine; + r#"uuid = { version = "^1.15", features = ["serde"] }"# + NewLine; StringContext::new().print_to_string(code) } From 54b945b3a77354fb8e372e384a0354a2a8a3deef Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Mon, 31 Mar 2025 12:31:00 +0200 Subject: [PATCH 2/3] Use display for GolemError --- src/rust/client_gen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/client_gen.rs b/src/rust/client_gen.rs index 0e1fae9..2b251dc 100644 --- a/src/rust/client_gen.rs +++ b/src/rust/client_gen.rs @@ -729,7 +729,7 @@ fn render_error_body_to_string(typ: &DataType) -> RustPrinter { + " { errors }) => { errors.join(\", \") }}" } DataType::Model(ModelType { name }) if name == "GolemErrorBody" => { - unit() + r#"format!("{:?}", body.golem_error)"# + unit() + r#"format!("{}", body.golem_error)"# } _ => unit() + r#"format!("{body:?}")"#, } From 610b0d0e1818462a9801f63f52f9c7fd39fc659a Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Mon, 31 Mar 2025 13:24:17 +0200 Subject: [PATCH 3/3] Clippy --- src/rust/client_gen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/client_gen.rs b/src/rust/client_gen.rs index 2b251dc..236468f 100644 --- a/src/rust/client_gen.rs +++ b/src/rust/client_gen.rs @@ -701,7 +701,7 @@ fn render_errors(method_name: &str, error_kind: &ErrorKind, errors: &MethodError indented( line(unit() + "fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {") + indented( - if errors.codes.len() > 0 { + if !errors.codes.is_empty() { line(unit() + "match self {") + indented(display_cases) + line(unit() + "}")