4
4
//! Define FFI compatible AgentResponse struct
5
5
6
6
use data_pipeline:: trace_exporter:: agent_response:: AgentResponse ;
7
- use std:: {
8
- ffi:: { c_char, CString } ,
9
- ptr:: null,
10
- } ;
7
+ use std:: ptr:: null;
11
8
12
9
/// Structure containing the agent response to a trace payload
13
10
/// MUST be freed with `ddog_trace_exporter_response_free`
@@ -18,18 +15,16 @@ use std::{
18
15
#[ derive( Debug , Default ) ]
19
16
pub struct ExporterResponse {
20
17
/// The body of the response, which is a string containing the response from the agent.
21
- pub body : CString ,
18
+ pub body : Option < Vec < u8 > > ,
22
19
}
23
20
24
21
impl From < AgentResponse > for ExporterResponse {
25
22
fn from ( value : AgentResponse ) -> Self {
26
23
match value {
27
24
AgentResponse :: Changed { body } => ExporterResponse {
28
- body : CString :: new ( body) . unwrap_or_default ( ) ,
29
- } ,
30
- AgentResponse :: Unchanged => ExporterResponse {
31
- body : CString :: new ( "" ) . unwrap_or_default ( ) ,
25
+ body : Some ( body. into_bytes ( ) ) ,
32
26
} ,
27
+ AgentResponse :: Unchanged => ExporterResponse { body : None } ,
33
28
}
34
29
}
35
30
}
@@ -39,12 +34,22 @@ impl From<AgentResponse> for ExporterResponse {
39
34
#[ no_mangle]
40
35
pub unsafe extern "C" fn ddog_trace_exporter_response_get_body (
41
36
response : * const ExporterResponse ,
42
- ) -> * const c_char {
43
- if response. is_null ( ) {
37
+ out_len : Option < & mut usize > ,
38
+ ) -> * const u8 {
39
+ let mut len: usize = 0 ;
40
+ let body = if response. is_null ( ) {
44
41
null ( )
42
+ } else if let Some ( body) = & ( * response) . body {
43
+ len = body. len ( ) ;
44
+ body. as_ptr ( )
45
45
} else {
46
- ( * response) . body . as_ptr ( )
46
+ null ( )
47
+ } ;
48
+
49
+ if let Some ( out_len) = out_len {
50
+ * out_len = len;
47
51
}
52
+ body
48
53
}
49
54
50
55
/// Free `response` and all its contents. After being called response will not point to a valid
@@ -59,28 +64,30 @@ pub unsafe extern "C" fn ddog_trace_exporter_response_free(response: *mut Export
59
64
#[ cfg( test) ]
60
65
mod tests {
61
66
use super :: * ;
62
- use std:: ffi:: CStr ;
63
67
64
68
#[ test]
65
69
fn constructor_test_changed ( ) {
66
70
let agent_response = AgentResponse :: Changed {
67
71
body : "res" . to_string ( ) ,
68
72
} ;
69
73
let response = & ExporterResponse :: from ( agent_response) as * const ExporterResponse ;
70
- let body = unsafe {
71
- CStr :: from_ptr ( ddog_trace_exporter_response_get_body ( response) ) . to_string_lossy ( )
72
- } ;
73
- assert_eq ! ( body, "res" . to_string( ) ) ;
74
+ let mut len = 0 ;
75
+ let body = unsafe { ddog_trace_exporter_response_get_body ( response, Some ( & mut len) ) } ;
76
+ let response =
77
+ unsafe { std:: str:: from_utf8 ( std:: slice:: from_raw_parts ( body, len) ) . unwrap ( ) } ;
78
+ assert_eq ! ( response, "res" ) ;
79
+ assert_eq ! ( len, 3 ) ;
74
80
}
75
81
76
82
#[ test]
77
83
fn constructor_test_unchanged ( ) {
78
84
let agent_response = AgentResponse :: Unchanged ;
79
85
let response = Box :: into_raw ( Box :: new ( ExporterResponse :: from ( agent_response) ) ) ;
80
- let body = unsafe {
81
- CStr :: from_ptr ( ddog_trace_exporter_response_get_body ( response) ) . to_string_lossy ( )
82
- } ;
83
- assert_eq ! ( body, "" . to_string( ) ) ;
86
+ let mut len = usize:: MAX ;
87
+ let body = unsafe { ddog_trace_exporter_response_get_body ( response, Some ( & mut len) ) } ;
88
+ assert ! ( body. is_null( ) ) ;
89
+ assert_eq ! ( len, 0 ) ;
90
+
84
91
unsafe {
85
92
ddog_trace_exporter_response_free ( response) ;
86
93
}
@@ -89,7 +96,7 @@ mod tests {
89
96
#[ test]
90
97
fn handle_null_test ( ) {
91
98
unsafe {
92
- let body = ddog_trace_exporter_response_get_body ( null ( ) ) ;
99
+ let body = ddog_trace_exporter_response_get_body ( null ( ) , None ) ;
93
100
assert ! ( body. is_null( ) ) ;
94
101
95
102
ddog_trace_exporter_response_free ( null :: < ExporterResponse > ( ) as * mut ExporterResponse ) ;
0 commit comments