@@ -611,8 +611,8 @@ impl CodeGenerator {
611611 ) -> Result <#response_type, ApiOpError <#op_error_type>> {
612612 #url_construction
613613
614- let mut req = #http_method_call
615- #request_body;
614+ let mut req = #http_method_call;
615+ #request_body
616616
617617 #query_params
618618 #header_params
@@ -706,7 +706,7 @@ impl CodeGenerator {
706706 let param_ident = Self :: to_field_ident ( & param_name_snake) ;
707707 let header_name = & param. name ;
708708 if param. required {
709- if param. rust_type == "String" {
709+ if Self :: param_uses_as_ref_str ( param) {
710710 emit. push ( quote ! {
711711 req = req. header( #header_name, #param_ident. as_ref( ) ) ;
712712 } ) ;
@@ -715,7 +715,7 @@ impl CodeGenerator {
715715 req = req. header( #header_name, #param_ident. to_string( ) ) ;
716716 } ) ;
717717 }
718- } else if param. rust_type == "String" {
718+ } else if Self :: param_uses_as_ref_str ( param) {
719719 emit. push ( quote ! {
720720 if let Some ( v) = #param_ident {
721721 req = req. header( #header_name, v. as_ref( ) ) ;
@@ -758,7 +758,7 @@ impl CodeGenerator {
758758
759759 if param. required {
760760 // Required parameters: always add
761- if param. rust_type == "String" {
761+ if Self :: param_uses_as_ref_str ( param) {
762762 param_building. push ( quote ! {
763763 query_params. push( ( #param_key, #param_name. as_ref( ) . to_string( ) ) ) ;
764764 } ) ;
@@ -769,7 +769,7 @@ impl CodeGenerator {
769769 }
770770 } else {
771771 // Optional parameters: add only if Some
772- if param. rust_type == "String" {
772+ if Self :: param_uses_as_ref_str ( param) {
773773 param_building. push ( quote ! {
774774 if let Some ( v) = #param_name {
775775 query_params. push( ( #param_key, v. as_ref( ) . to_string( ) ) ) ;
@@ -993,43 +993,72 @@ impl CodeGenerator {
993993 }
994994 }
995995
996+ /// True when the parameter's compile-time type is `impl AsRef<str>` and
997+ /// we should call `.as_ref()` on it before stringifying. False for any
998+ /// $ref-resolved type (T10) or non-String primitive — those just call
999+ /// `.to_string()`.
1000+ fn param_uses_as_ref_str ( param : & crate :: analysis:: ParameterInfo ) -> bool {
1001+ param. schema_ref . is_none ( ) && param. rust_type == "String"
1002+ }
1003+
9961004 /// Generate request body serialization based on content type
1005+ /// Emit statements that mutate `req` to apply the request body. Returns
1006+ /// `quote!{}` if the operation has no body. Optional bodies (T11) gate the
1007+ /// application on `Some(_)`; required bodies apply unconditionally.
9971008 fn generate_request_body ( & self , op : & OperationInfo ) -> TokenStream {
998- if let Some ( ref rb) = op. request_body {
999- use crate :: analysis:: RequestBodyContent ;
1000- match rb {
1001- RequestBodyContent :: Json { .. } => {
1002- quote ! {
1009+ let Some ( rb) = op. request_body . as_ref ( ) else {
1010+ return quote ! { } ;
1011+ } ;
1012+ use crate :: analysis:: RequestBodyContent ;
1013+ let required = op. request_body_required ;
1014+ let ( ident, apply) : ( TokenStream , TokenStream ) = match rb {
1015+ RequestBodyContent :: Json { .. } => (
1016+ quote ! { request } ,
1017+ quote ! {
1018+ req = req
10031019 . body( serde_json:: to_vec( & request) . map_err( HttpError :: serialization_error) ?)
1004- . header( "content-type" , "application/json" )
1005- }
1006- }
1007- RequestBodyContent :: FormUrlEncoded { .. } => {
1008- quote ! {
1020+ . header( "content-type" , "application/json" ) ;
1021+ } ,
1022+ ) ,
1023+ RequestBodyContent :: FormUrlEncoded { .. } => (
1024+ quote ! { request } ,
1025+ quote ! {
1026+ req = req
10091027 . body( serde_urlencoded:: to_string( & request) . map_err( HttpError :: serialization_error) ?)
1010- . header( "content-type" , "application/x-www-form-urlencoded" )
1011- }
1012- }
1013- RequestBodyContent :: Multipart => {
1014- quote ! {
1015- . multipart( form)
1016- }
1017- }
1018- RequestBodyContent :: OctetStream => {
1019- quote ! {
1028+ . header( "content-type" , "application/x-www-form-urlencoded" ) ;
1029+ } ,
1030+ ) ,
1031+ RequestBodyContent :: Multipart => (
1032+ quote ! { form } ,
1033+ quote ! {
1034+ req = req. multipart( form) ;
1035+ } ,
1036+ ) ,
1037+ RequestBodyContent :: OctetStream => (
1038+ quote ! { body } ,
1039+ quote ! {
1040+ req = req
10201041 . body( body)
1021- . header( "content-type" , "application/octet-stream" )
1022- }
1023- }
1024- RequestBodyContent :: TextPlain => {
1025- quote ! {
1042+ . header( "content-type" , "application/octet-stream" ) ;
1043+ } ,
1044+ ) ,
1045+ RequestBodyContent :: TextPlain => (
1046+ quote ! { body } ,
1047+ quote ! {
1048+ req = req
10261049 . body( body)
1027- . header( "content-type" , "text/plain" )
1028- }
1050+ . header( "content-type" , "text/plain" ) ;
1051+ } ,
1052+ ) ,
1053+ } ;
1054+ if required {
1055+ apply
1056+ } else {
1057+ quote ! {
1058+ if let Some ( #ident) = #ident {
1059+ #apply
10291060 }
10301061 }
1031- } else {
1032- quote ! { }
10331062 }
10341063 }
10351064
@@ -1258,7 +1287,7 @@ impl CodeGenerator {
12581287 let param_name_snake = self . sanitize_param_name ( & param. name ) ;
12591288 let param_ident = Self :: to_field_ident ( & param_name_snake) ;
12601289
1261- if param. rust_type == "String" {
1290+ if Self :: param_uses_as_ref_str ( param) {
12621291 format_args. push ( quote ! {
12631292 __pct_encode_path_segment( #param_ident. as_ref( ) )
12641293 } ) ;
0 commit comments