11use std:: collections:: BTreeMap ;
22
33use syn:: { FnArg , PatType , Type } ;
4- use vespera_core:: {
5- route:: { MediaType , Operation , Parameter , ParameterLocation , RequestBody , Response } ,
6- schema:: { Schema , SchemaRef } ,
7- } ;
4+ use vespera_core:: route:: { MediaType , Operation , Parameter , ParameterLocation , Response } ;
85
96use super :: {
107 parameters:: parse_function_parameter, path:: extract_path_parameters,
@@ -160,49 +157,6 @@ pub fn build_operation_from_function(
160157 }
161158 }
162159
163- // Fallback: if last arg is String/&str and no body yet, treat as text/plain body
164- if request_body. is_none ( )
165- && let Some ( FnArg :: Typed ( PatType { ty, .. } ) ) = sig. inputs . last ( )
166- {
167- let is_string = match ty. as_ref ( ) {
168- Type :: Path ( type_path) => type_path
169- . path
170- . segments
171- . last ( )
172- . map ( |s| s. ident == "String" || s. ident == "str" )
173- . unwrap_or ( false ) ,
174- Type :: Reference ( type_ref) => {
175- if let Type :: Path ( p) = type_ref. elem . as_ref ( ) {
176- p. path
177- . segments
178- . last ( )
179- . map ( |s| s. ident == "String" || s. ident == "str" )
180- . unwrap_or ( false )
181- } else {
182- false
183- }
184- }
185- _ => false ,
186- } ;
187-
188- if is_string {
189- let mut content = BTreeMap :: new ( ) ;
190- content. insert (
191- "text/plain" . to_string ( ) ,
192- MediaType {
193- schema : Some ( SchemaRef :: Inline ( Box :: new ( Schema :: string ( ) ) ) ) ,
194- example : None ,
195- examples : None ,
196- } ,
197- ) ;
198- request_body = Some ( RequestBody {
199- description : None ,
200- content,
201- required : Some ( true ) ,
202- } ) ;
203- }
204- }
205-
206160 // Parse return type - may return multiple responses (for Result types)
207161 let mut responses = parse_return_type ( & sig. output , known_schemas, struct_definitions) ;
208162
@@ -588,8 +542,8 @@ mod tests {
588542 }
589543
590544 #[ test]
591- fn test_string_body_fallback ( ) {
592- // Test lines 100-107: String as last arg becomes text/plain body
545+ fn test_string_body ( ) {
546+ // String arg is handled by parse_request_body via is_string_like()
593547 let op = build ( "fn upload(content: String) -> String" , "/upload" , None ) ;
594548
595549 let body = op. request_body . as_ref ( ) . expect ( "request body expected" ) ;
@@ -604,32 +558,27 @@ mod tests {
604558 }
605559
606560 #[ test]
607- fn test_str_ref_body_fallback ( ) {
608- // Test lines 100-106: &str as last arg becomes text/plain body
561+ fn test_str_ref_body ( ) {
562+ // &str arg is handled by parse_request_body via is_string_like()
609563 let op = build ( "fn upload(content: &str) -> String" , "/upload" , None ) ;
610564
611565 let body = op. request_body . as_ref ( ) . expect ( "request body expected" ) ;
612566 assert ! ( body. content. contains_key( "text/plain" ) ) ;
613567 }
614568
615569 #[ test]
616- fn test_type_reference_with_string ( ) {
617- // Test lines 100-102, 104: Type::Reference branch - &String
570+ fn test_string_ref_body ( ) {
571+ // &String arg is handled by parse_request_body via is_string_like()
618572 let op = build ( "fn upload(content: &String) -> String" , "/upload" , None ) ;
619573
620- // &String reference should be detected as string type
621- // Line 101-102 checks if Type::Reference elem is a Path with String/str
622574 let body = op. request_body . as_ref ( ) . expect ( "request body expected" ) ;
623575 assert ! ( body. content. contains_key( "text/plain" ) ) ;
624576 }
625577
626578 #[ test]
627- fn test_non_string_last_arg_not_body ( ) {
628- // Test line 107: last arg that's NOT String/&str should NOT become body
579+ fn test_non_string_arg_not_body ( ) {
580+ // Non-string args don't become request body
629581 let op = build ( "fn process(count: i32) -> String" , "/process" , None ) ;
630-
631- // i32 is not String/&str, so line 107 returns false, no body created
632- // However, bare i32 without extractor is also ignored
633582 assert ! ( op. request_body. is_none( ) ) ;
634583 }
635584
@@ -651,38 +600,33 @@ mod tests {
651600
652601 #[ test]
653602 fn test_reference_to_non_path_type_not_body ( ) {
654- // Test line 104: &(tuple) reference where elem is NOT a Path type
655- // This hits the else branch at line 104 returning false
603+ // &(tuple) is not string-like, no body created
656604 let op = build ( "fn process(data: &(i32, i32)) -> String" , "/process" , None ) ;
657- // Reference to tuple is not String/&str, so no body created
658605 assert ! ( op. request_body. is_none( ) ) ;
659606 }
660607
661608 #[ test]
662609 fn test_reference_to_slice_not_body ( ) {
663- // Test line 104: &[T] reference where elem is NOT a simple Path type
610+ // &[T] is not string-like, no body created
664611 let op = build ( "fn process(data: &[u8]) -> String" , "/process" , None ) ;
665- // Reference to slice is not String/&str
666612 assert ! ( op. request_body. is_none( ) ) ;
667613 }
668614
669615 #[ test]
670616 fn test_tuple_type_not_body ( ) {
671- // Test line 107: tuple type ( not Path, not Reference) returns false
617+ // Tuple type is not string-like, no body created
672618 let op = build (
673619 "fn process(data: (i32, String)) -> String" ,
674620 "/process" ,
675621 None ,
676622 ) ;
677- // Tuple is neither Path nor Reference, hits line 107
678623 assert ! ( op. request_body. is_none( ) ) ;
679624 }
680625
681626 #[ test]
682627 fn test_array_type_not_body ( ) {
683- // Test line 107: array type ( not Path, not Reference) returns false
628+ // Array type is not string-like, no body created
684629 let op = build ( "fn process(data: [u8; 4]) -> String" , "/process" , None ) ;
685- // Array is neither Path nor Reference
686630 assert ! ( op. request_body. is_none( ) ) ;
687631 }
688632
0 commit comments