1#![cfg_attr(not(feature = "std"), no_std)]
12#![allow(unused_doc_comments)]
13extern crate alloc;
35
36extern crate core;
37#[cfg(feature = "std")]
38extern crate std;
39#[cfg(feature = "std")]
40use std::io::Error;
41
42use crate::config::{
43 DataEndpoint, DataType, get_endpoint_meta, get_message_meta, max_data_type_id, max_endpoint_id,
44 runtime_static_hex_length, runtime_static_string_length,
45};
46use crate::macros::{ReprI32Enum, ReprU32Enum};
47use alloc::sync::Arc;
48use core::fmt::Formatter;
49use core::mem::size_of;
50use core::ops::Mul;
51
52#[cfg(all(test, feature = "std"))]
57mod tests;
58
59#[cfg(feature = "python")]
60#[cfg(feature = "std")]
61mod python_api;
62
63#[cfg(all(not(feature = "std"), target_os = "none"))]
71unsafe extern "C" {
72 fn seds_error_msg(msg: *const u8, len: usize);
73}
74
75#[cfg(all(not(feature = "std"), target_os = "none"))]
76mod embedded_alloc {
77 use core::alloc::{GlobalAlloc, Layout};
78 use core::mem::size_of;
79
80 unsafe extern "C" {
81 fn telemetryMalloc(size: usize) -> *mut core::ffi::c_void;
82 fn telemetryFree(ptr: *mut core::ffi::c_void);
83 fn telemetry_panic_hook(msg: *const u8, len: usize);
84 }
85
86 struct TelemetryAlloc;
89
90 #[inline]
91 fn align_up(addr: usize, align: usize) -> usize {
92 (addr + (align - 1)) & !(align - 1)
93 }
94
95 unsafe impl GlobalAlloc for TelemetryAlloc {
96 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
97 let align = layout.align().max(size_of::<usize>());
98 let header = size_of::<usize>();
99 let total = match layout
100 .size()
101 .checked_add(align)
102 .and_then(|v| v.checked_add(header))
103 {
104 Some(v) => v,
105 None => return core::ptr::null_mut(),
106 };
107
108 let raw = unsafe { telemetryMalloc(total) as *mut u8 };
109 if raw.is_null() {
110 return core::ptr::null_mut();
111 }
112
113 let base = raw as usize + header;
114 let aligned = align_up(base, align) as *mut u8;
115
116 unsafe {
118 let slot = (aligned as *mut usize).offset(-1);
119 *slot = raw as usize;
120 }
121
122 aligned
123 }
124
125 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
126 if ptr.is_null() {
127 return;
128 }
129
130 let raw = unsafe {
131 let slot = (ptr as *mut usize).offset(-1);
132 *slot as *mut core::ffi::c_void
133 };
134 unsafe { telemetryFree(raw) };
135 }
136 }
137
138 #[global_allocator]
139 static A: TelemetryAlloc = TelemetryAlloc;
140
141 use core::panic::PanicInfo;
143
144 #[panic_handler]
145 fn panic(_info: &PanicInfo) -> ! {
146 let msg = b"rust panic";
147 unsafe {
148 telemetry_panic_hook(msg.as_ptr(), msg.len());
149 }
150
151 loop {}
153 }
154
155 }
158
159#[cfg(any(feature = "std", feature = "fair-admission"))]
167mod admission_fairness;
168mod binding_options;
169mod c_api;
170pub mod config;
171#[cfg(feature = "cryptography")]
172pub mod crypto;
173pub mod diagnostics;
174#[cfg(feature = "discovery")]
175pub mod discovery;
176mod lock;
177mod macros;
178pub mod memory_admission;
179pub mod packet;
180mod shared_bytes;
181pub use shared_bytes::SharedBytes;
182#[cfg(feature = "compact-packet-store")]
183pub mod packet_store;
184mod queue;
185pub mod relay;
186pub mod router;
187mod side_transport;
188mod small_payload;
189mod small_sort;
190#[cfg(feature = "timesync")]
191pub mod timesync;
192mod type_stats;
193mod varint;
194pub mod wire_format;
195pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
201
202pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
204
205pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
207
208impl ReprU32Enum for DataType {
209 const MAX: u32 = u32::MAX;
210
211 #[inline]
212 fn from_u32(x: u32) -> Option<Self> {
213 DataType::try_from_u32(x)
214 }
215}
216
217impl ReprU32Enum for DataEndpoint {
218 const MAX: u32 = u32::MAX;
219
220 #[inline]
221 fn from_u32(x: u32) -> Option<Self> {
222 DataEndpoint::try_from_u32(x)
223 }
224}
225
226#[inline]
227pub fn current_max_endpoint_id() -> u32 {
228 max_endpoint_id()
229}
230
231#[inline]
232pub fn current_max_data_type_id() -> u32 {
233 max_data_type_id()
234}
235
236#[repr(i32)]
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
238pub enum RouteSelectionMode {
239 Fanout = 0,
240 Weighted = 1,
241 Failover = 2,
242}
243
244impl_repr_i32_enum!(
245 RouteSelectionMode,
246 RouteSelectionMode::Fanout as i32,
247 RouteSelectionMode::Failover as i32
248);
249
250#[inline]
251const fn parse_usize(s: &str) -> usize {
252 let bytes = s.as_bytes();
253 let mut i = 0;
254 let mut val = 0;
255
256 while i < bytes.len() {
257 let c = bytes[i];
258 if c < b'0' || c > b'9' {
259 panic!("Invalid digit");
260 }
261 val = val * 10 + (c - b'0') as usize;
262 i += 1;
263 }
264 val
265}
266
267#[inline]
268pub const fn parse_f64(s: &str) -> f64 {
269 let bytes = s.as_bytes();
270 let mut i = 0;
271
272 if bytes.is_empty() {
273 panic!("empty string");
274 }
275
276 let mut sign = 1.0;
278 if bytes[i] == b'-' {
279 sign = -1.0;
280 i += 1;
281 } else if bytes[i] == b'+' {
282 i += 1;
283 }
284
285 let mut int_part: f64 = 0.0;
286 let mut has_digits = false;
287
288 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
289 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
290 i += 1;
291 has_digits = true;
292 }
293
294 let mut frac_part: f64 = 0.0;
295 let mut scale: f64 = 1.0;
296
297 if i < bytes.len() && bytes[i] == b'.' {
298 i += 1;
299
300 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
301 scale *= 10.0;
302 frac_part += (bytes[i] - b'0') as f64 / scale;
303 i += 1;
304 has_digits = true;
305 }
306 }
307
308 if !has_digits || i != bytes.len() {
309 panic!("invalid f64 literal");
310 }
311
312 sign * (int_part + frac_part)
313}
314
315#[inline(always)]
316const fn parse_strings(s: &str) -> &str {
317 s
318}
319
320#[inline]
321pub const fn parse_u8(s: &str) -> u8 {
322 let bytes = s.as_bytes();
323 let mut i = 0;
324 let mut val: u16 = 0;
325
326 if bytes.is_empty() {
327 panic!("empty string");
328 }
329
330 while i < bytes.len() {
331 let c = bytes[i];
332 if c < b'0' || c > b'9' {
333 panic!("invalid digit in u8");
334 }
335
336 val = val * 10 + (c - b'0') as u16;
337 if val > 255 {
338 panic!("u8 overflow");
339 }
340
341 i += 1;
342 }
343
344 val as u8
345}
346
347#[inline]
348pub const fn parse_u128(s: &str) -> u128 {
349 let bytes = s.as_bytes();
350 let mut i = 0;
351 let mut val: u128 = 0;
352
353 if bytes.is_empty() {
354 panic!("empty string");
355 }
356
357 while i < bytes.len() {
358 let c = bytes[i];
359 if c < b'0' || c > b'9' {
360 panic!("invalid digit in u128");
361 }
362
363 let digit = (c - b'0') as u128;
364
365 if val > (u128::MAX - digit) / 10 {
368 panic!("u128 overflow");
369 }
370
371 val = val * 10 + digit;
372 i += 1;
373 }
374
375 val
376}
377
378#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
382pub struct EndpointMeta {
383 #[cfg(feature = "std")]
385 name: Arc<str>,
386 #[cfg(not(feature = "std"))]
387 name: &'static str,
388 #[cfg(feature = "std")]
390 description: Arc<str>,
391 #[cfg(not(feature = "std"))]
392 description: &'static str,
393 link_local_only: bool,
395}
396
397impl EndpointMeta {
398 #[cfg(feature = "std")]
399 pub(crate) fn name_ref(&self) -> &str {
400 self.name.as_ref()
401 }
402
403 #[cfg(not(feature = "std"))]
404 pub(crate) fn name_ref(&self) -> &str {
405 self.name
406 }
407
408 #[cfg(feature = "std")]
409 pub(crate) fn description_ref(&self) -> &str {
410 self.description.as_ref()
411 }
412
413 #[cfg(not(feature = "std"))]
414 pub(crate) fn description_ref(&self) -> &str {
415 self.description
416 }
417
418 #[cfg(feature = "std")]
424 pub fn as_str(&self) -> Arc<str> {
425 self.name.clone()
426 }
427
428 #[cfg(not(feature = "std"))]
429 pub fn as_str(&self) -> &'static str {
430 self.name
431 }
432
433 #[inline]
435 #[cfg(feature = "std")]
436 pub fn description(&self) -> Arc<str> {
437 self.description.clone()
438 }
439
440 #[cfg(not(feature = "std"))]
441 pub fn description(&self) -> &'static str {
442 self.description
443 }
444
445 #[inline]
447 pub fn is_link_local_only(&self) -> bool {
448 self.link_local_only
449 }
450}
451
452impl DataEndpoint {
453 #[cfg(feature = "std")]
459 pub fn as_str(&self) -> Arc<str> {
460 get_endpoint_meta(*self).name
461 }
462
463 #[cfg(not(feature = "std"))]
464 pub fn as_str(&self) -> &'static str {
465 get_endpoint_meta(*self).name
466 }
467
468 #[cfg(feature = "std")]
470 pub fn description(&self) -> Arc<str> {
471 get_endpoint_meta(*self).description
472 }
473
474 #[cfg(not(feature = "std"))]
475 pub fn description(&self) -> &'static str {
476 get_endpoint_meta(*self).description
477 }
478
479 #[inline]
481 pub fn is_link_local_only(&self) -> bool {
482 get_endpoint_meta(*self).link_local_only
483 }
484}
485
486#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
488pub enum MessageElement {
489 Static(usize, MessageDataType, MessageClass),
493 Dynamic(MessageDataType, MessageClass),
497}
498
499impl MessageElement {
500 #[inline]
502 pub const fn data_type(&self) -> MessageDataType {
503 match self {
504 MessageElement::Static(_, dt, _) => *dt,
505 MessageElement::Dynamic(dt, _) => *dt,
506 }
507 }
508
509 #[inline]
511 pub const fn message_type(&self) -> MessageClass {
512 match self {
513 MessageElement::Static(_, _, mt) => *mt,
514 MessageElement::Dynamic(_, mt) => *mt,
515 }
516 }
517}
518
519#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
521#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
522pub enum ReliableMode {
523 #[cfg_attr(feature = "serde", serde(rename = "Off"))]
525 None,
526 Ordered,
528 Unordered,
530}
531
532#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
534pub enum E2eEncryptionPolicy {
535 PreferOff,
537 PreferOn,
539 RequireOn,
541}
542
543#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
545pub struct MessageMeta {
546 #[cfg(feature = "std")]
547 name: Arc<str>,
548 #[cfg(not(feature = "std"))]
549 name: &'static str,
550 #[cfg(feature = "std")]
552 description: Arc<str>,
553 #[cfg(not(feature = "std"))]
554 description: &'static str,
555 element: MessageElement,
557 #[cfg(feature = "std")]
559 endpoints: Arc<[DataEndpoint]>,
560 #[cfg(not(feature = "std"))]
561 endpoints: &'static [DataEndpoint],
562 reliable: ReliableMode,
564 priority: u8,
566 e2e_encryption: E2eEncryptionPolicy,
568}
569
570impl MessageMeta {
571 #[cfg(feature = "std")]
572 pub(crate) fn name_ref(&self) -> &str {
573 self.name.as_ref()
574 }
575
576 #[cfg(not(feature = "std"))]
577 pub(crate) fn name_ref(&self) -> &str {
578 self.name
579 }
580
581 #[cfg(feature = "std")]
582 pub(crate) fn description_ref(&self) -> &str {
583 self.description.as_ref()
584 }
585
586 #[cfg(not(feature = "std"))]
587 pub(crate) fn description_ref(&self) -> &str {
588 self.description
589 }
590
591 #[cfg(feature = "std")]
592 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
593 self.endpoints.as_ref()
594 }
595
596 #[cfg(not(feature = "std"))]
597 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
598 self.endpoints
599 }
600}
601
602impl DataType {
603 #[cfg(feature = "std")]
605 pub fn as_str(&self) -> Arc<str> {
606 get_message_meta(*self).name
607 }
608
609 #[cfg(not(feature = "std"))]
610 pub fn as_str(&self) -> &'static str {
611 get_message_meta(*self).name
612 }
613
614 #[cfg(feature = "std")]
616 pub fn description(&self) -> Arc<str> {
617 get_message_meta(*self).description
618 }
619
620 #[cfg(not(feature = "std"))]
621 pub fn description(&self) -> &'static str {
622 get_message_meta(*self).description
623 }
624}
625#[inline]
631pub fn message_meta(ty: DataType) -> MessageMeta {
632 get_message_meta(ty)
633}
634
635#[inline]
637pub fn is_reliable_type(ty: DataType) -> bool {
638 !matches!(get_message_meta(ty).reliable, ReliableMode::None)
639}
640
641#[inline]
643pub fn reliable_mode(ty: DataType) -> ReliableMode {
644 get_message_meta(ty).reliable
645}
646
647#[inline]
649pub fn message_priority(ty: DataType) -> u8 {
650 get_message_meta(ty).priority
651}
652
653#[inline]
661pub fn transport_priority(ty: DataType) -> u8 {
662 match ty {
663 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
666 255
667 }
668
669 DataType::DiscoveryAnnounce
671 | DataType::DiscoveryTimeSyncSources
672 | DataType::DiscoveryTopology
673 | DataType::DiscoveryTopologyRequest
674 | DataType::DiscoveryLeave
675 | DataType::DiscoveryLinkCapabilities
676 | DataType::DiscoveryAddress => 255,
677
678 DataType::DiscoverySchema
683 | DataType::DiscoverySchemaRequest
684 | DataType::ManagedVariableRequest
685 | DataType::ManagedVariableValue
686 | DataType::TimeSyncAnnounce
687 | DataType::TimeSyncRequest
688 | DataType::TimeSyncResponse => 254,
689
690 _ => message_priority(ty).min(253),
692 }
693}
694
695#[inline]
698pub(crate) fn small_frozen_control(
699 ty: DataType,
700 owners: usize,
701 shape: Option<MessageElement>,
702) -> bool {
703 if !(1..=3).contains(&owners) {
704 return false;
705 }
706 config::try_get_message_meta(ty).is_some_and(|meta| {
707 matches!(
708 meta.element,
709 MessageElement::Static(0..=16, MessageDataType::UInt8, _)
710 ) && matches!(
711 shape,
712 None | Some(MessageElement::Static(0..=16, MessageDataType::UInt8, _))
713 )
714 })
715}
716
717#[inline]
719pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
720 transport_priority(ty)
721}
722
723#[inline]
725pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
726 get_message_meta(ty).e2e_encryption
727}
728
729impl Mul<MessageElement> for usize {
732 type Output = usize;
733
734 #[inline]
735 fn mul(self, rhs: MessageElement) -> usize {
736 self * rhs.into()
737 }
738}
739
740impl Mul<usize> for MessageElement {
741 type Output = usize;
742
743 #[inline]
744 fn mul(self, rhs: usize) -> usize {
745 self.into() * rhs
746 }
747}
748
749impl MessageElement {
750 #[inline]
755 fn into(self) -> usize {
756 match self {
757 MessageElement::Static(a, _, _) => a,
758 _ => 0,
759 }
760 }
761}
762
763#[inline]
773pub fn get_needed_message_size(ty: DataType) -> usize {
774 data_type_size(get_data_type(ty)) * get_message_meta(ty).element
775}
776
777#[inline]
783pub fn get_info_type(ty: DataType) -> MessageClass {
784 get_message_meta(ty).element.message_type()
785}
786
787#[inline]
794pub fn get_data_type(ty: DataType) -> MessageDataType {
795 get_message_meta(ty).element.data_type()
796}
797
798#[inline]
804#[cfg(feature = "std")]
805pub fn get_message_name(ty: DataType) -> Arc<str> {
806 get_message_meta(ty).name
807}
808
809#[cfg(not(feature = "std"))]
810pub fn get_message_name(ty: DataType) -> &'static str {
811 get_message_meta(ty).name
812}
813
814#[inline]
820#[cfg(feature = "std")]
821pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
822 get_message_meta(ty).endpoints
823}
824
825#[cfg(not(feature = "std"))]
826pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
827 get_message_meta(ty).endpoints
828}
829
830#[allow(dead_code)]
835#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
836pub enum MessageDataType {
837 Float64,
838 Float32,
839 UInt8,
840 UInt16,
841 UInt32,
842 UInt64,
843 UInt128,
844 Int8,
845 Int16,
846 Int32,
847 Int64,
848 Int128,
849 Bool,
850 String,
851 Binary,
852 NoData,
853}
854
855#[inline]
864pub fn data_type_size(dt: MessageDataType) -> usize {
865 match dt {
866 MessageDataType::Float64 => size_of::<f64>(),
867 MessageDataType::Float32 => size_of::<f32>(),
868 MessageDataType::UInt8 => size_of::<u8>(),
869 MessageDataType::UInt16 => size_of::<u16>(),
870 MessageDataType::UInt32 => size_of::<u32>(),
871 MessageDataType::UInt64 => size_of::<u64>(),
872 MessageDataType::UInt128 => size_of::<u128>(),
873 MessageDataType::Int8 => size_of::<i8>(),
874 MessageDataType::Int16 => size_of::<i16>(),
875 MessageDataType::Int32 => size_of::<i32>(),
876 MessageDataType::Int64 => size_of::<i64>(),
877 MessageDataType::Int128 => size_of::<i128>(),
878 MessageDataType::Bool => size_of::<bool>(),
879 MessageDataType::String => runtime_static_string_length(),
880 MessageDataType::Binary => runtime_static_hex_length(),
881 MessageDataType::NoData => 0,
882 }
883}
884
885#[allow(dead_code)]
887#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
888pub enum MessageClass {
889 Data,
891 Error,
893 Warning,
895}
896
897#[derive(Debug, Clone, PartialEq, Eq)]
906pub enum TelemetryError {
907 GenericError(Option<Arc<str>>),
909
910 InvalidType,
912
913 SizeMismatch { expected: usize, got: usize },
915
916 SizeMismatchError,
918
919 EmptyEndpoints,
921
922 TimestampInvalid,
924
925 MissingPayload,
927
928 HandlerError(&'static str),
930
931 BadArg,
933
934 PermissionDenied,
936
937 Pack(&'static str),
939
940 Unpack(&'static str),
942
943 Io(&'static str),
945
946 InvalidUtf8,
948
949 TypeMismatch { expected: usize, got: usize },
951
952 InvalidLinkId(&'static str),
954
955 PacketTooLarge(&'static str),
957}
958
959impl TelemetryError {
960 pub const fn to_error_code(&self) -> TelemetryErrorCode {
963 match self {
964 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
965 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
966 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
967 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
968 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
969 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
970 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
971 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
972 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
973 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
974 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
975 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
976 TelemetryError::Io(_) => TelemetryErrorCode::Io,
977 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
978 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
979 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
980 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
981 }
982 }
983}
984
985impl core::fmt::Display for TelemetryError {
987 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
988 core::fmt::Debug::fmt(self, f)
993 }
994}
995
996#[cfg(feature = "std")]
998impl std::error::Error for TelemetryError {
999 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1000 None
1001 }
1002}
1003
1004#[cfg(feature = "std")]
1006impl From<Error> for TelemetryError {
1007 fn from(error: Error) -> Self {
1008 let str = error.to_string();
1009 let astr: Arc<str> = Arc::from(str.as_str());
1010 TelemetryError::GenericError(Some(astr))
1011 }
1012}
1013
1014#[cfg(feature = "std")]
1016impl From<Box<dyn std::error::Error>> for TelemetryError {
1017 fn from(err: Box<dyn std::error::Error>) -> Self {
1018 let str = err.to_string();
1019 let astr: Arc<str> = Arc::from(str.as_str());
1020 TelemetryError::GenericError(Some(astr))
1021 }
1022}
1023
1024#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1029#[repr(i32)]
1030pub enum TelemetryErrorCode {
1031 GenericError = -2,
1032 InvalidType = -3,
1033 SizeMismatch = -4,
1034 SizeMismatchError = -5,
1035 EmptyEndpoints = -6,
1036 TimestampInvalid = -7,
1037 MissingPayload = -8,
1038 HandlerError = -9,
1039 BadArg = -10,
1040 PermissionDenied = -11,
1041 Pack = -12,
1042 Unpack = -13,
1043 Io = -14,
1044 InvalidUtf8 = -15,
1045 TypeMismatch = -16,
1046 InvalidLinkId = -17,
1047 PacketTooLarge = -18,
1048}
1049
1050impl_repr_i32_enum!(
1052 TelemetryErrorCode,
1053 TelemetryErrorCode::MAX,
1054 TelemetryErrorCode::MIN
1055);
1056
1057impl TelemetryErrorCode {
1058 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1060
1061 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1063
1064 #[inline]
1068 pub fn as_str(&self) -> &'static str {
1069 match self {
1070 TelemetryErrorCode::GenericError => "GenericError",
1071 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1072 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1073 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1074 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1075 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1076 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1077 TelemetryErrorCode::HandlerError => "{Handler Error}",
1078 TelemetryErrorCode::BadArg => "{Bad Arg}",
1079 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1080 TelemetryErrorCode::Pack => "{Pack Error}",
1081 TelemetryErrorCode::Unpack => "{Unpack Error}",
1082 TelemetryErrorCode::Io => "{IO Error}",
1083 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1084 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1085 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1086 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1087 }
1088 }
1089
1090 #[inline]
1098 pub fn try_from_i32(x: i32) -> Option<Self> {
1099 try_enum_from_i32(x)
1100 }
1101}
1102
1103pub type TelemetryResult<T> = Result<T, TelemetryError>;
1105
1106#[inline]
1118pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1119 if x > E::MAX {
1120 return None;
1121 }
1122 E::from_u32(x)
1123}
1124
1125#[inline]
1133pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1134 if x < E::MIN || x > E::MAX {
1135 return None;
1136 }
1137
1138 let e = unsafe { (&x as *const i32 as *const E).read() };
1140 Some(e)
1141}