1use crate::dispatcher;
16use crate::types::*;
17use std::ptr::{null, null_mut};
18use std::time::{Duration, SystemTime, UNIX_EPOCH};
19
20use crate::error::{HostCallError, HostResponseError, Result};
21
22pub const NO_HEADERS: &[(&[u8], &[u8])] = &[];
24
25pub const NO_BODY: Option<&[u8]> = None;
27
28pub const NO_TRAILERS: &[(&[u8], &[u8])] = &[];
30
31mod abi {
32 pub const PROXY_LOG: &str = "proxy_log";
33 pub const PROXY_GET_CURRENT_TIME_NANOSECONDS: &str = "proxy_get_current_time_nanoseconds";
34 pub const PROXY_SET_TICK_PERIOD_MILLISECONDS: &str = "proxy_set_tick_period_milliseconds";
35 pub const PROXY_GET_BUFFER_BYTES: &str = "proxy_get_buffer_bytes";
36 pub const PROXY_SET_BUFFER_BYTES: &str = "proxy_set_buffer_bytes";
37 pub const PROXY_GET_HEADER_MAP_PAIRS: &str = "proxy_get_header_map_pairs";
38 pub const PROXY_SET_HEADER_MAP_PAIRS: &str = "proxy_set_header_map_pairs";
39 pub const PROXY_GET_HEADER_MAP_VALUE: &str = "proxy_get_header_map_value";
40 pub const PROXY_REPLACE_HEADER_MAP_VALUE: &str = "proxy_replace_header_map_value";
41 pub const PROXY_REMOVE_HEADER_MAP_VALUE: &str = "proxy_remove_header_map_value";
42 pub const PROXY_ADD_HEADER_MAP_VALUE: &str = "proxy_add_header_map_value";
43 pub const PROXY_GET_PROPERTY: &str = "proxy_get_property";
44 pub const PROXY_SET_PROPERTY: &str = "proxy_set_property";
45 pub const PROXY_GET_SHARED_DATA: &str = "proxy_get_shared_data";
46 pub const PROXY_SET_SHARED_DATA: &str = "proxy_set_shared_data";
47 pub const PROXY_REGISTER_SHARED_QUEUE: &str = "proxy_register_shared_queue";
48 pub const PROXY_RESOLVE_SHARED_QUEUE: &str = "proxy_resolve_shared_queue";
49 pub const PROXY_DEQUEUE_SHARED_QUEUE: &str = "proxy_dequeue_shared_queue";
50 pub const PROXY_ENQUEUE_SHARED_QUEUE: &str = "proxy_enqueue_shared_queue";
51 pub const PROXY_CONTINUE_STREAM: &str = "proxy_continue_stream";
52 pub const PROXY_CLOSE_STREAM: &str = "proxy_close_stream";
53 pub const PROXY_SEND_LOCAL_RESPONSE: &str = "proxy_send_local_response";
54 pub const PROXY_HTTP_CALL: &str = "proxy_http_call";
55 pub const PROXY_SET_EFFECTIVE_CONTEXT: &str = "proxy_set_effective_context";
56 pub const PROXY_DONE: &str = "proxy_done";
57 pub const PROXY_DEFINE_METRIC: &str = "proxy_define_metric";
58 pub const PROXY_GET_METRIC: &str = "proxy_get_metric";
59 pub const PROXY_RECORD_METRIC: &str = "proxy_record_metric";
60 pub const PROXY_INCREMENT_METRIC: &str = "proxy_increment_metric";
61}
62
63extern "C" {
64 fn proxy_log(level: LogLevel, message_data: *const u8, message_size: usize) -> Status;
65}
66
67pub fn log(level: LogLevel, message: &str) -> Result<()> {
69 unsafe {
70 match proxy_log(level, message.as_ptr(), message.len()) {
71 Status::Ok => Ok(()),
72 status => Err(HostCallError::new(abi::PROXY_LOG, status).into()),
73 }
74 }
75}
76
77extern "C" {
78 fn proxy_get_current_time_nanoseconds(return_time: *mut u64) -> Status;
79}
80
81pub fn get_current_time() -> Result<SystemTime> {
83 let mut return_time: u64 = 0;
84 unsafe {
85 match proxy_get_current_time_nanoseconds(&mut return_time) {
86 Status::Ok => Ok(UNIX_EPOCH + Duration::from_nanos(return_time)),
87 status => {
88 Err(HostCallError::new(abi::PROXY_GET_CURRENT_TIME_NANOSECONDS, status).into())
89 }
90 }
91 }
92}
93
94extern "C" {
95 fn proxy_set_tick_period_milliseconds(period: u32) -> Status;
96}
97
98pub fn set_tick_period(period: Duration) -> Result<()> {
100 unsafe {
101 match proxy_set_tick_period_milliseconds(period.as_millis() as u32) {
102 Status::Ok => Ok(()),
103 status => {
104 Err(HostCallError::new(abi::PROXY_SET_TICK_PERIOD_MILLISECONDS, status).into())
105 }
106 }
107 }
108}
109
110extern "C" {
111 fn proxy_get_buffer_bytes(
112 buffer_type: BufferType,
113 start: usize,
114 max_size: usize,
115 return_buffer_data: *mut *mut u8,
116 return_buffer_size: *mut usize,
117 ) -> Status;
118}
119
120pub fn get_buffer(
122 buffer_type: BufferType,
123 start: usize,
124 max_size: usize,
125) -> Result<Option<ByteString>> {
126 let mut return_data: *mut u8 = null_mut();
127 let mut return_size: usize = 0;
128 unsafe {
129 match proxy_get_buffer_bytes(
130 buffer_type,
131 start,
132 max_size,
133 &mut return_data,
134 &mut return_size,
135 ) {
136 Status::Ok => {
137 if !return_data.is_null() {
138 Ok(Vec::from_raw_parts(return_data, return_size, return_size))
139 .map(ByteString::from)
140 .map(Option::from)
141 } else {
142 Ok(None)
143 }
144 }
145 Status::NotFound => Ok(None),
146 status => Err(HostCallError::new(abi::PROXY_GET_BUFFER_BYTES, status).into()),
147 }
148 }
149}
150
151extern "C" {
152 fn proxy_set_buffer_bytes(
153 buffer_type: BufferType,
154 start: usize,
155 size: usize,
156 buffer_data: *const u8,
157 buffer_size: usize,
158 ) -> Status;
159}
160
161pub fn set_buffer<B>(buffer_type: BufferType, start: usize, size: usize, value: B) -> Result<()>
175where
176 B: AsRef<[u8]>,
177{
178 unsafe {
179 match proxy_set_buffer_bytes(
180 buffer_type,
181 start,
182 size,
183 value.as_ref().as_ptr(),
184 value.as_ref().len(),
185 ) {
186 Status::Ok => Ok(()),
187 status => Err(HostCallError::new(abi::PROXY_SET_BUFFER_BYTES, status).into()),
188 }
189 }
190}
191
192extern "C" {
193 fn proxy_get_header_map_pairs(
194 map_type: MapType,
195 return_map_data: *mut *mut u8,
196 return_map_size: *mut usize,
197 ) -> Status;
198}
199
200pub fn get_map(map_type: MapType) -> Result<Vec<(ByteString, ByteString)>> {
202 unsafe {
203 let mut return_data: *mut u8 = null_mut();
204 let mut return_size: usize = 0;
205 match proxy_get_header_map_pairs(map_type, &mut return_data, &mut return_size) {
206 Status::Ok => {
207 if !return_data.is_null() {
208 let serialized_map = Vec::from_raw_parts(return_data, return_size, return_size);
209 utils::deserialize_map(&serialized_map).map_err(|err| {
210 HostResponseError::new(abi::PROXY_GET_HEADER_MAP_PAIRS, err).into()
211 })
212 } else {
213 Ok(Vec::new())
214 }
215 }
216 status => Err(HostCallError::new(abi::PROXY_GET_HEADER_MAP_PAIRS, status).into()),
217 }
218 }
219}
220
221extern "C" {
222 fn proxy_set_header_map_pairs(
223 map_type: MapType,
224 map_data: *const u8,
225 map_size: usize,
226 ) -> Status;
227}
228
229pub fn set_map<K, V>(map_type: MapType, map: &[(K, V)]) -> Result<()>
247where
248 K: AsRef<[u8]>,
249 V: AsRef<[u8]>,
250{
251 let serialized_map = utils::serialize_map(map);
252 unsafe {
253 match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) {
254 Status::Ok => Ok(()),
255 status => Err(HostCallError::new(abi::PROXY_SET_HEADER_MAP_PAIRS, status).into()),
256 }
257 }
258}
259
260extern "C" {
261 fn proxy_get_header_map_value(
262 map_type: MapType,
263 key_data: *const u8,
264 key_size: usize,
265 return_value_data: *mut *mut u8,
266 return_value_size: *mut usize,
267 ) -> Status;
268}
269
270pub fn get_map_value<K>(map_type: MapType, key: K) -> Result<Option<ByteString>>
285where
286 K: AsRef<[u8]>,
287{
288 let mut return_data: *mut u8 = null_mut();
289 let mut return_size: usize = 0;
290 unsafe {
291 match proxy_get_header_map_value(
292 map_type,
293 key.as_ref().as_ptr(),
294 key.as_ref().len(),
295 &mut return_data,
296 &mut return_size,
297 ) {
298 Status::Ok => {
299 if !return_data.is_null() {
300 Ok(Vec::from_raw_parts(return_data, return_size, return_size))
301 .map(ByteString::from)
302 .map(Option::from)
303 } else {
304 Ok(None)
305 }
306 }
307 status => Err(HostCallError::new(abi::PROXY_GET_HEADER_MAP_VALUE, status).into()),
308 }
309 }
310}
311
312extern "C" {
313 fn proxy_replace_header_map_value(
314 map_type: MapType,
315 key_data: *const u8,
316 key_size: usize,
317 value_data: *const u8,
318 value_size: usize,
319 ) -> Status;
320}
321
322extern "C" {
323 fn proxy_remove_header_map_value(
324 map_type: MapType,
325 key_data: *const u8,
326 key_size: usize,
327 ) -> Status;
328}
329
330pub fn set_map_value<K, V>(map_type: MapType, key: K, value: Option<V>) -> Result<()>
345where
346 K: AsRef<[u8]>,
347 V: AsRef<[u8]>,
348{
349 unsafe {
350 if let Some(value) = value {
351 match proxy_replace_header_map_value(
352 map_type,
353 key.as_ref().as_ptr(),
354 key.as_ref().len(),
355 value.as_ref().as_ptr(),
356 value.as_ref().len(),
357 ) {
358 Status::Ok => Ok(()),
359 status => {
360 Err(HostCallError::new(abi::PROXY_REPLACE_HEADER_MAP_VALUE, status).into())
361 }
362 }
363 } else {
364 match proxy_remove_header_map_value(map_type, key.as_ref().as_ptr(), key.as_ref().len())
365 {
366 Status::Ok => Ok(()),
367 status => {
368 Err(HostCallError::new(abi::PROXY_REMOVE_HEADER_MAP_VALUE, status).into())
369 }
370 }
371 }
372 }
373}
374
375extern "C" {
376 fn proxy_add_header_map_value(
377 map_type: MapType,
378 key_data: *const u8,
379 key_size: usize,
380 value_data: *const u8,
381 value_size: usize,
382 ) -> Status;
383}
384
385pub fn add_map_value<K, V>(map_type: MapType, key: K, value: V) -> Result<()>
400where
401 K: AsRef<[u8]>,
402 V: AsRef<[u8]>,
403{
404 unsafe {
405 match proxy_add_header_map_value(
406 map_type,
407 key.as_ref().as_ptr(),
408 key.as_ref().len(),
409 value.as_ref().as_ptr(),
410 value.as_ref().len(),
411 ) {
412 Status::Ok => Ok(()),
413 status => Err(HostCallError::new(abi::PROXY_ADD_HEADER_MAP_VALUE, status).into()),
414 }
415 }
416}
417
418extern "C" {
419 fn proxy_get_property(
420 path_data: *const u8,
421 path_size: usize,
422 return_value_data: *mut *mut u8,
423 return_value_size: *mut usize,
424 ) -> Status;
425}
426
427pub fn get_property<P>(path: &[P]) -> Result<Option<ByteString>>
441where
442 P: AsRef<str>,
443{
444 let serialized_path = utils::serialize_property_path(path);
445 let mut return_data: *mut u8 = null_mut();
446 let mut return_size: usize = 0;
447 unsafe {
448 match proxy_get_property(
449 serialized_path.as_ptr(),
450 serialized_path.len(),
451 &mut return_data,
452 &mut return_size,
453 ) {
454 Status::Ok => {
455 if !return_data.is_null() {
456 Ok(Vec::from_raw_parts(return_data, return_size, return_size))
457 .map(ByteString::from)
458 .map(Option::from)
459 } else {
460 Ok(None)
461 }
462 }
463 Status::NotFound => Ok(None),
464 status => Err(HostCallError::new(abi::PROXY_GET_PROPERTY, status).into()),
465 }
466 }
467}
468
469extern "C" {
470 fn proxy_set_property(
471 path_data: *const u8,
472 path_size: usize,
473 value_data: *const u8,
474 value_size: usize,
475 ) -> Status;
476}
477
478pub fn set_property<P, V>(path: &[P], value: Option<V>) -> Result<()>
492where
493 P: AsRef<str>,
494 V: AsRef<[u8]>,
495{
496 let serialized_path = utils::serialize_property_path(path);
497 let (value_ptr, value_len) = value.map_or((null(), 0), |value| {
498 (value.as_ref().as_ptr(), value.as_ref().len())
499 });
500 unsafe {
501 match proxy_set_property(
502 serialized_path.as_ptr(),
503 serialized_path.len(),
504 value_ptr,
505 value_len,
506 ) {
507 Status::Ok => Ok(()),
508 status => Err(HostCallError::new(abi::PROXY_SET_PROPERTY, status).into()),
509 }
510 }
511}
512
513extern "C" {
514 fn proxy_get_shared_data(
515 key_data: *const u8,
516 key_size: usize,
517 return_value_data: *mut *mut u8,
518 return_value_size: *mut usize,
519 return_cas: *mut u32,
520 ) -> Status;
521}
522
523pub fn get_shared_data<K>(key: K) -> Result<(Option<ByteString>, Option<u32>)>
537where
538 K: AsRef<str>,
539{
540 let mut return_data: *mut u8 = null_mut();
541 let mut return_size: usize = 0;
542 let mut return_cas: u32 = 0;
543 unsafe {
544 match proxy_get_shared_data(
545 key.as_ref().as_ptr(),
546 key.as_ref().len(),
547 &mut return_data,
548 &mut return_size,
549 &mut return_cas,
550 ) {
551 Status::Ok => {
552 let cas = match return_cas {
553 0 => None,
554 cas => Some(cas),
555 };
556 if !return_data.is_null() {
557 Ok((
558 Some(Vec::from_raw_parts(return_data, return_size, return_size))
559 .map(ByteString::from),
560 cas,
561 ))
562 } else {
563 Ok((None, cas))
564 }
565 }
566 Status::NotFound => Ok((None, None)),
567 status => Err(HostCallError::new(abi::PROXY_GET_SHARED_DATA, status).into()),
568 }
569 }
570}
571
572extern "C" {
573 fn proxy_set_shared_data(
574 key_data: *const u8,
575 key_size: usize,
576 value_data: *const u8,
577 value_size: usize,
578 cas: u32,
579 ) -> Status;
580}
581
582pub fn set_shared_data<K, V>(key: K, value: Option<V>, cas: Option<u32>) -> Result<()>
596where
597 K: AsRef<str>,
598 V: AsRef<[u8]>,
599{
600 let (value_ptr, value_len) = value.map_or((null(), 0), |value| {
601 (value.as_ref().as_ptr(), value.as_ref().len())
602 });
603 unsafe {
604 match proxy_set_shared_data(
605 key.as_ref().as_ptr(),
606 key.as_ref().len(),
607 value_ptr,
608 value_len,
609 cas.unwrap_or(0),
610 ) {
611 Status::Ok => Ok(()),
612 status => Err(HostCallError::new(abi::PROXY_SET_SHARED_DATA, status).into()),
613 }
614 }
615}
616
617extern "C" {
618 fn proxy_register_shared_queue(
619 name_data: *const u8,
620 name_size: usize,
621 return_id: *mut u32,
622 ) -> Status;
623}
624
625pub fn register_shared_queue(name: &str) -> Result<u32> {
627 unsafe {
628 let mut return_id: u32 = 0;
629 match proxy_register_shared_queue(name.as_ptr(), name.len(), &mut return_id) {
630 Status::Ok => Ok(return_id),
631 status => Err(HostCallError::new(abi::PROXY_REGISTER_SHARED_QUEUE, status).into()),
632 }
633 }
634}
635
636extern "C" {
637 fn proxy_resolve_shared_queue(
638 vm_id_data: *const u8,
639 vm_id_size: usize,
640 name_data: *const u8,
641 name_size: usize,
642 return_id: *mut u32,
643 ) -> Status;
644}
645
646pub fn resolve_shared_queue(vm_id: &str, name: &str) -> Result<Option<u32>> {
648 let mut return_id: u32 = 0;
649 unsafe {
650 match proxy_resolve_shared_queue(
651 vm_id.as_ptr(),
652 vm_id.len(),
653 name.as_ptr(),
654 name.len(),
655 &mut return_id,
656 ) {
657 Status::Ok => Ok(Some(return_id)),
658 Status::NotFound => Ok(None),
659 status => Err(HostCallError::new(abi::PROXY_RESOLVE_SHARED_QUEUE, status).into()),
660 }
661 }
662}
663
664extern "C" {
665 fn proxy_dequeue_shared_queue(
666 queue_id: u32,
667 return_value_data: *mut *mut u8,
668 return_value_size: *mut usize,
669 ) -> Status;
670}
671
672pub fn dequeue_shared_queue(queue_id: u32) -> Result<Option<ByteString>> {
674 let mut return_data: *mut u8 = null_mut();
675 let mut return_size: usize = 0;
676 unsafe {
677 match proxy_dequeue_shared_queue(queue_id, &mut return_data, &mut return_size) {
678 Status::Ok => {
679 if !return_data.is_null() {
680 Ok(Vec::from_raw_parts(return_data, return_size, return_size))
681 .map(ByteString::from)
682 .map(Option::from)
683 } else {
684 Ok(None)
685 }
686 }
687 Status::Empty => Ok(None),
688 status => Err(HostCallError::new(abi::PROXY_DEQUEUE_SHARED_QUEUE, status).into()),
689 }
690 }
691}
692
693extern "C" {
694 fn proxy_enqueue_shared_queue(
695 queue_id: u32,
696 value_data: *const u8,
697 value_size: usize,
698 ) -> Status;
699}
700
701pub fn enqueue_shared_queue<V>(queue_id: u32, value: Option<V>) -> Result<()>
715where
716 V: AsRef<[u8]>,
717{
718 let (value_ptr, value_len) = value.map_or((null(), 0), |value| {
719 (value.as_ref().as_ptr(), value.as_ref().len())
720 });
721 unsafe {
722 match proxy_enqueue_shared_queue(queue_id, value_ptr, value_len) {
723 Status::Ok => Ok(()),
724 status => Err(HostCallError::new(abi::PROXY_ENQUEUE_SHARED_QUEUE, status).into()),
725 }
726 }
727}
728
729extern "C" {
730 fn proxy_continue_stream(stream: StreamType) -> Status;
731}
732
733pub fn continue_stream(stream_type: StreamType) -> Result<()> {
735 unsafe {
736 match proxy_continue_stream(stream_type) {
737 Status::Ok => Ok(()),
738 status => Err(HostCallError::new(abi::PROXY_CONTINUE_STREAM, status).into()),
739 }
740 }
741}
742
743extern "C" {
744 fn proxy_close_stream(stream: StreamType) -> Status;
745}
746
747pub fn close_stream(stream_type: StreamType) -> Result<()> {
749 unsafe {
750 match proxy_close_stream(stream_type) {
751 Status::Ok => Ok(()),
752 status => Err(HostCallError::new(abi::PROXY_CLOSE_STREAM, status).into()),
753 }
754 }
755}
756
757extern "C" {
758 fn proxy_send_local_response(
759 status_code: u32,
760 status_code_details_data: *const u8,
761 status_code_details_size: usize,
762 body_data: *const u8,
763 body_size: usize,
764 headers_data: *const u8,
765 headers_size: usize,
766 grpc_status: i32,
767 ) -> Status;
768}
769
770pub fn send_http_response<K, V, B>(
788 status_code: u32,
789 headers: &[(K, V)],
790 body: Option<B>,
791) -> Result<()>
792where
793 K: AsRef<[u8]>,
794 V: AsRef<[u8]>,
795 B: AsRef<[u8]>,
796{
797 let serialized_headers = utils::serialize_map(headers);
798 let (body_ptr, body_len) = body.map_or((null(), 0), |body| {
799 (body.as_ref().as_ptr(), body.as_ref().len())
800 });
801 unsafe {
802 match proxy_send_local_response(
803 status_code,
804 null(),
805 0,
806 body_ptr,
807 body_len,
808 serialized_headers.as_ptr(),
809 serialized_headers.len(),
810 -1,
811 ) {
812 Status::Ok => Ok(()),
813 status => Err(HostCallError::new(abi::PROXY_SEND_LOCAL_RESPONSE, status).into()),
814 }
815 }
816}
817
818extern "C" {
819 fn proxy_http_call(
820 upstream_data: *const u8,
821 upstream_size: usize,
822 headers_data: *const u8,
823 headers_size: usize,
824 body_data: *const u8,
825 body_size: usize,
826 trailers_data: *const u8,
827 trailers_size: usize,
828 timeout: u32,
829 return_token: *mut u32,
830 ) -> Status;
831}
832
833pub fn dispatch_http_call<K1, V1, K2, V2, B>(
857 upstream: &str,
858 headers: &[(K1, V1)],
859 body: Option<B>,
860 trailers: &[(K2, V2)],
861 timeout: Duration,
862) -> Result<u32>
863where
864 K1: AsRef<[u8]>,
865 V1: AsRef<[u8]>,
866 K2: AsRef<[u8]>,
867 V2: AsRef<[u8]>,
868 B: AsRef<[u8]>,
869{
870 let serialized_headers = utils::serialize_map(headers);
871 let serialized_trailers = utils::serialize_map(trailers);
872 let (body_ptr, body_len) = body.map_or((null(), 0), |body| {
873 (body.as_ref().as_ptr(), body.as_ref().len())
874 });
875 let mut return_token: u32 = 0;
876 unsafe {
877 match proxy_http_call(
878 upstream.as_ptr(),
879 upstream.len(),
880 serialized_headers.as_ptr(),
881 serialized_headers.len(),
882 body_ptr,
883 body_len,
884 serialized_trailers.as_ptr(),
885 serialized_trailers.len(),
886 timeout.as_millis() as u32,
887 &mut return_token,
888 ) {
889 Status::Ok => {
890 dispatcher::register_callout(return_token);
891 Ok(return_token)
892 }
893 status => Err(HostCallError::new(abi::PROXY_HTTP_CALL, status).into()),
894 }
895 }
896}
897
898extern "C" {
899 fn proxy_set_effective_context(context_id: u32) -> Status;
900}
901
902pub fn set_effective_context(context_id: u32) -> Result<()> {
904 unsafe {
905 match proxy_set_effective_context(context_id) {
906 Status::Ok => Ok(()),
907 status => Err(HostCallError::new(abi::PROXY_SET_EFFECTIVE_CONTEXT, status).into()),
908 }
909 }
910}
911
912extern "C" {
913 fn proxy_done() -> Status;
914}
915
916pub fn done() -> Result<()> {
918 unsafe {
919 match proxy_done() {
920 Status::Ok => Ok(()),
921 status => Err(HostCallError::new(abi::PROXY_DONE, status).into()),
922 }
923 }
924}
925
926extern "C" {
927 fn proxy_define_metric(
928 metric_type: MetricType,
929 name_data: *const u8,
930 name_size: usize,
931 return_id: *mut u32,
932 ) -> Status;
933}
934
935pub fn define_metric(metric_type: MetricType, name: &str) -> Result<u32> {
936 let mut return_id: u32 = 0;
937 unsafe {
938 match proxy_define_metric(metric_type, name.as_ptr(), name.len(), &mut return_id) {
939 Status::Ok => Ok(return_id),
940 status => Err(HostCallError::new(abi::PROXY_DEFINE_METRIC, status).into()),
941 }
942 }
943}
944
945extern "C" {
946 fn proxy_get_metric(metric_id: u32, return_value: *mut u64) -> Status;
947}
948
949pub fn get_metric(metric_id: u32) -> Result<u64> {
950 let mut return_value: u64 = 0;
951 unsafe {
952 match proxy_get_metric(metric_id, &mut return_value) {
953 Status::Ok => Ok(return_value),
954 status => Err(HostCallError::new(abi::PROXY_GET_METRIC, status).into()),
955 }
956 }
957}
958
959extern "C" {
960 fn proxy_record_metric(metric_id: u32, value: u64) -> Status;
961}
962
963pub fn record_metric(metric_id: u32, value: u64) -> Result<()> {
964 unsafe {
965 match proxy_record_metric(metric_id, value) {
966 Status::Ok => Ok(()),
967 status => Err(HostCallError::new(abi::PROXY_RECORD_METRIC, status).into()),
968 }
969 }
970}
971
972extern "C" {
973 fn proxy_increment_metric(metric_id: u32, offset: i64) -> Status;
974}
975
976pub fn increment_metric(metric_id: u32, offset: i64) -> Result<()> {
977 unsafe {
978 match proxy_increment_metric(metric_id, offset) {
979 Status::Ok => Ok(()),
980 status => Err(HostCallError::new(abi::PROXY_INCREMENT_METRIC, status).into()),
981 }
982 }
983}
984
985mod utils {
986 use crate::error::Result;
987 use crate::types::ByteString;
988 use std::convert::TryFrom;
989
990 pub(super) fn serialize_property_path<P>(path: &[P]) -> Vec<u8>
991 where
992 P: AsRef<str>,
993 {
994 if path.is_empty() {
995 return Vec::new();
996 }
997 let mut size: usize = 0;
998 for part in path {
999 size += part.as_ref().len() + 1;
1000 }
1001 let mut bytes: Vec<u8> = Vec::with_capacity(size);
1002 for part in path {
1003 bytes.extend_from_slice(part.as_ref().as_bytes());
1004 bytes.push(0);
1005 }
1006 bytes.pop();
1007 bytes
1008 }
1009
1010 pub(super) fn serialize_map<K, V>(map: &[(K, V)]) -> Vec<u8>
1011 where
1012 K: AsRef<[u8]>,
1013 V: AsRef<[u8]>,
1014 {
1015 let mut size: usize = 4;
1016 for (name, value) in map {
1017 size += name.as_ref().len() + value.as_ref().len() + 10;
1018 }
1019 let mut bytes: Vec<u8> = Vec::with_capacity(size);
1020 bytes.extend_from_slice(&map.len().to_le_bytes());
1021 for (name, value) in map {
1022 bytes.extend_from_slice(&name.as_ref().len().to_le_bytes());
1023 bytes.extend_from_slice(&value.as_ref().len().to_le_bytes());
1024 }
1025 for (name, value) in map {
1026 bytes.extend_from_slice(name.as_ref());
1027 bytes.push(0);
1028 bytes.extend_from_slice(value.as_ref());
1029 bytes.push(0);
1030 }
1031 bytes
1032 }
1033
1034 pub(super) fn deserialize_map(bytes: &[u8]) -> Result<Vec<(ByteString, ByteString)>> {
1035 let mut map = Vec::new();
1036 if bytes.is_empty() {
1037 return Ok(map);
1038 }
1039 let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[0..4])?) as usize;
1040 let mut p = 4 + size * 8;
1041 for n in 0..size {
1042 let s = 4 + n * 8;
1043 let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s..s + 4])?) as usize;
1044 let key = bytes[p..p + size].to_vec();
1045 p += size + 1;
1046 let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s + 4..s + 8])?) as usize;
1047 let value = bytes[p..p + size].to_vec();
1048 p += size + 1;
1049 map.push((key.into(), value.into()));
1050 }
1051 Ok(map)
1052 }
1053}