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
159mod binding_options;
167mod c_api;
168pub mod config;
169#[cfg(feature = "cryptography")]
170pub mod crypto;
171pub mod diagnostics;
172#[cfg(feature = "discovery")]
173pub mod discovery;
174mod lock;
175mod macros;
176pub mod memory_admission;
177pub mod packet;
178mod shared_bytes;
179pub use shared_bytes::SharedBytes;
180#[cfg(feature = "compact-packet-store")]
181pub mod packet_store;
182mod queue;
183pub mod relay;
184pub mod router;
185mod side_transport;
186mod small_payload;
187#[cfg(feature = "timesync")]
188pub mod timesync;
189pub mod wire_format;
190pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
196
197pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
199
200pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
202
203impl ReprU32Enum for DataType {
204 const MAX: u32 = MAX_VALUE_DATA_TYPE;
205
206 #[inline]
207 fn from_u32(x: u32) -> Option<Self> {
208 DataType::try_from_u32(x)
209 }
210}
211
212impl ReprU32Enum for DataEndpoint {
213 const MAX: u32 = MAX_VALUE_DATA_ENDPOINT;
214
215 #[inline]
216 fn from_u32(x: u32) -> Option<Self> {
217 DataEndpoint::try_from_u32(x)
218 }
219}
220
221#[inline]
222pub fn current_max_endpoint_id() -> u32 {
223 max_endpoint_id()
224}
225
226#[inline]
227pub fn current_max_data_type_id() -> u32 {
228 max_data_type_id()
229}
230
231#[repr(i32)]
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
233pub enum RouteSelectionMode {
234 Fanout = 0,
235 Weighted = 1,
236 Failover = 2,
237}
238
239impl_repr_i32_enum!(
240 RouteSelectionMode,
241 RouteSelectionMode::Fanout as i32,
242 RouteSelectionMode::Failover as i32
243);
244
245#[inline]
246const fn parse_usize(s: &str) -> usize {
247 let bytes = s.as_bytes();
248 let mut i = 0;
249 let mut val = 0;
250
251 while i < bytes.len() {
252 let c = bytes[i];
253 if c < b'0' || c > b'9' {
254 panic!("Invalid digit");
255 }
256 val = val * 10 + (c - b'0') as usize;
257 i += 1;
258 }
259 val
260}
261
262#[inline]
263pub const fn parse_f64(s: &str) -> f64 {
264 let bytes = s.as_bytes();
265 let mut i = 0;
266
267 if bytes.is_empty() {
268 panic!("empty string");
269 }
270
271 let mut sign = 1.0;
273 if bytes[i] == b'-' {
274 sign = -1.0;
275 i += 1;
276 } else if bytes[i] == b'+' {
277 i += 1;
278 }
279
280 let mut int_part: f64 = 0.0;
281 let mut has_digits = false;
282
283 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
284 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
285 i += 1;
286 has_digits = true;
287 }
288
289 let mut frac_part: f64 = 0.0;
290 let mut scale: f64 = 1.0;
291
292 if i < bytes.len() && bytes[i] == b'.' {
293 i += 1;
294
295 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
296 scale *= 10.0;
297 frac_part += (bytes[i] - b'0') as f64 / scale;
298 i += 1;
299 has_digits = true;
300 }
301 }
302
303 if !has_digits || i != bytes.len() {
304 panic!("invalid f64 literal");
305 }
306
307 sign * (int_part + frac_part)
308}
309
310#[inline(always)]
311const fn parse_strings(s: &str) -> &str {
312 s
313}
314
315#[inline]
316pub const fn parse_u8(s: &str) -> u8 {
317 let bytes = s.as_bytes();
318 let mut i = 0;
319 let mut val: u16 = 0;
320
321 if bytes.is_empty() {
322 panic!("empty string");
323 }
324
325 while i < bytes.len() {
326 let c = bytes[i];
327 if c < b'0' || c > b'9' {
328 panic!("invalid digit in u8");
329 }
330
331 val = val * 10 + (c - b'0') as u16;
332 if val > 255 {
333 panic!("u8 overflow");
334 }
335
336 i += 1;
337 }
338
339 val as u8
340}
341
342#[inline]
343pub const fn parse_u128(s: &str) -> u128 {
344 let bytes = s.as_bytes();
345 let mut i = 0;
346 let mut val: u128 = 0;
347
348 if bytes.is_empty() {
349 panic!("empty string");
350 }
351
352 while i < bytes.len() {
353 let c = bytes[i];
354 if c < b'0' || c > b'9' {
355 panic!("invalid digit in u128");
356 }
357
358 let digit = (c - b'0') as u128;
359
360 if val > (u128::MAX - digit) / 10 {
363 panic!("u128 overflow");
364 }
365
366 val = val * 10 + digit;
367 i += 1;
368 }
369
370 val
371}
372
373#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
377pub struct EndpointMeta {
378 #[cfg(feature = "std")]
380 name: Arc<str>,
381 #[cfg(not(feature = "std"))]
382 name: &'static str,
383 #[cfg(feature = "std")]
385 description: Arc<str>,
386 #[cfg(not(feature = "std"))]
387 description: &'static str,
388 link_local_only: bool,
390}
391
392impl EndpointMeta {
393 #[cfg(feature = "std")]
394 pub(crate) fn name_ref(&self) -> &str {
395 self.name.as_ref()
396 }
397
398 #[cfg(not(feature = "std"))]
399 pub(crate) fn name_ref(&self) -> &str {
400 self.name
401 }
402
403 #[cfg(feature = "std")]
404 pub(crate) fn description_ref(&self) -> &str {
405 self.description.as_ref()
406 }
407
408 #[cfg(not(feature = "std"))]
409 pub(crate) fn description_ref(&self) -> &str {
410 self.description
411 }
412
413 #[cfg(feature = "std")]
419 pub fn as_str(&self) -> Arc<str> {
420 self.name.clone()
421 }
422
423 #[cfg(not(feature = "std"))]
424 pub fn as_str(&self) -> &'static str {
425 self.name
426 }
427
428 #[inline]
430 #[cfg(feature = "std")]
431 pub fn description(&self) -> Arc<str> {
432 self.description.clone()
433 }
434
435 #[cfg(not(feature = "std"))]
436 pub fn description(&self) -> &'static str {
437 self.description
438 }
439
440 #[inline]
442 pub fn is_link_local_only(&self) -> bool {
443 self.link_local_only
444 }
445}
446
447impl DataEndpoint {
448 #[cfg(feature = "std")]
454 pub fn as_str(&self) -> Arc<str> {
455 get_endpoint_meta(*self).name
456 }
457
458 #[cfg(not(feature = "std"))]
459 pub fn as_str(&self) -> &'static str {
460 get_endpoint_meta(*self).name
461 }
462
463 #[cfg(feature = "std")]
465 pub fn description(&self) -> Arc<str> {
466 get_endpoint_meta(*self).description
467 }
468
469 #[cfg(not(feature = "std"))]
470 pub fn description(&self) -> &'static str {
471 get_endpoint_meta(*self).description
472 }
473
474 #[inline]
476 pub fn is_link_local_only(&self) -> bool {
477 get_endpoint_meta(*self).link_local_only
478 }
479}
480
481#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
483pub enum MessageElement {
484 Static(usize, MessageDataType, MessageClass),
488 Dynamic(MessageDataType, MessageClass),
492}
493
494impl MessageElement {
495 #[inline]
497 pub const fn data_type(&self) -> MessageDataType {
498 match self {
499 MessageElement::Static(_, dt, _) => *dt,
500 MessageElement::Dynamic(dt, _) => *dt,
501 }
502 }
503
504 #[inline]
506 pub const fn message_type(&self) -> MessageClass {
507 match self {
508 MessageElement::Static(_, _, mt) => *mt,
509 MessageElement::Dynamic(_, mt) => *mt,
510 }
511 }
512}
513
514#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
516pub enum ReliableMode {
517 None,
519 Ordered,
521 Unordered,
523}
524
525#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
527pub enum E2eEncryptionPolicy {
528 PreferOff,
530 PreferOn,
532 RequireOn,
534}
535
536#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
538pub struct MessageMeta {
539 #[cfg(feature = "std")]
540 name: Arc<str>,
541 #[cfg(not(feature = "std"))]
542 name: &'static str,
543 #[cfg(feature = "std")]
545 description: Arc<str>,
546 #[cfg(not(feature = "std"))]
547 description: &'static str,
548 element: MessageElement,
550 #[cfg(feature = "std")]
552 endpoints: Arc<[DataEndpoint]>,
553 #[cfg(not(feature = "std"))]
554 endpoints: &'static [DataEndpoint],
555 reliable: ReliableMode,
557 priority: u8,
559 e2e_encryption: E2eEncryptionPolicy,
561}
562
563impl MessageMeta {
564 #[cfg(feature = "std")]
565 pub(crate) fn name_ref(&self) -> &str {
566 self.name.as_ref()
567 }
568
569 #[cfg(not(feature = "std"))]
570 pub(crate) fn name_ref(&self) -> &str {
571 self.name
572 }
573
574 #[cfg(feature = "std")]
575 pub(crate) fn description_ref(&self) -> &str {
576 self.description.as_ref()
577 }
578
579 #[cfg(not(feature = "std"))]
580 pub(crate) fn description_ref(&self) -> &str {
581 self.description
582 }
583
584 #[cfg(feature = "std")]
585 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
586 self.endpoints.as_ref()
587 }
588
589 #[cfg(not(feature = "std"))]
590 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
591 self.endpoints
592 }
593}
594
595impl DataType {
596 #[cfg(feature = "std")]
598 pub fn as_str(&self) -> Arc<str> {
599 get_message_meta(*self).name
600 }
601
602 #[cfg(not(feature = "std"))]
603 pub fn as_str(&self) -> &'static str {
604 get_message_meta(*self).name
605 }
606
607 #[cfg(feature = "std")]
609 pub fn description(&self) -> Arc<str> {
610 get_message_meta(*self).description
611 }
612
613 #[cfg(not(feature = "std"))]
614 pub fn description(&self) -> &'static str {
615 get_message_meta(*self).description
616 }
617}
618#[inline]
624pub fn message_meta(ty: DataType) -> MessageMeta {
625 get_message_meta(ty)
626}
627
628#[inline]
630pub fn is_reliable_type(ty: DataType) -> bool {
631 !matches!(get_message_meta(ty).reliable, ReliableMode::None)
632}
633
634#[inline]
636pub fn reliable_mode(ty: DataType) -> ReliableMode {
637 get_message_meta(ty).reliable
638}
639
640#[inline]
642pub fn message_priority(ty: DataType) -> u8 {
643 get_message_meta(ty).priority
644}
645
646#[inline]
654pub fn transport_priority(ty: DataType) -> u8 {
655 match ty {
656 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
659 255
660 }
661
662 DataType::DiscoveryAnnounce
664 | DataType::DiscoveryTimeSyncSources
665 | DataType::DiscoveryTopology
666 | DataType::DiscoveryTopologyRequest
667 | DataType::DiscoveryLeave
668 | DataType::DiscoveryLinkCapabilities
669 | DataType::DiscoveryAddress => 255,
670
671 DataType::DiscoverySchema
676 | DataType::DiscoverySchemaRequest
677 | DataType::ManagedVariableRequest
678 | DataType::ManagedVariableValue
679 | DataType::TimeSyncAnnounce
680 | DataType::TimeSyncRequest
681 | DataType::TimeSyncResponse => 254,
682
683 _ => message_priority(ty).min(253),
685 }
686}
687
688#[inline]
691pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
692 transport_priority(ty)
693}
694
695#[inline]
697pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
698 get_message_meta(ty).e2e_encryption
699}
700
701impl Mul<MessageElement> for usize {
704 type Output = usize;
705
706 #[inline]
707 fn mul(self, rhs: MessageElement) -> usize {
708 self * rhs.into()
709 }
710}
711
712impl Mul<usize> for MessageElement {
713 type Output = usize;
714
715 #[inline]
716 fn mul(self, rhs: usize) -> usize {
717 self.into() * rhs
718 }
719}
720
721impl MessageElement {
722 #[inline]
727 fn into(self) -> usize {
728 match self {
729 MessageElement::Static(a, _, _) => a,
730 _ => 0,
731 }
732 }
733}
734
735#[inline]
745pub fn get_needed_message_size(ty: DataType) -> usize {
746 data_type_size(get_data_type(ty)) * get_message_meta(ty).element
747}
748
749#[inline]
755pub fn get_info_type(ty: DataType) -> MessageClass {
756 get_message_meta(ty).element.message_type()
757}
758
759#[inline]
766pub fn get_data_type(ty: DataType) -> MessageDataType {
767 get_message_meta(ty).element.data_type()
768}
769
770#[inline]
776#[cfg(feature = "std")]
777pub fn get_message_name(ty: DataType) -> Arc<str> {
778 get_message_meta(ty).name
779}
780
781#[cfg(not(feature = "std"))]
782pub fn get_message_name(ty: DataType) -> &'static str {
783 get_message_meta(ty).name
784}
785
786#[inline]
792#[cfg(feature = "std")]
793pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
794 get_message_meta(ty).endpoints
795}
796
797#[cfg(not(feature = "std"))]
798pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
799 get_message_meta(ty).endpoints
800}
801
802#[allow(dead_code)]
807#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
808pub enum MessageDataType {
809 Float64,
810 Float32,
811 UInt8,
812 UInt16,
813 UInt32,
814 UInt64,
815 UInt128,
816 Int8,
817 Int16,
818 Int32,
819 Int64,
820 Int128,
821 Bool,
822 String,
823 Binary,
824 NoData,
825}
826
827#[inline]
836pub fn data_type_size(dt: MessageDataType) -> usize {
837 match dt {
838 MessageDataType::Float64 => size_of::<f64>(),
839 MessageDataType::Float32 => size_of::<f32>(),
840 MessageDataType::UInt8 => size_of::<u8>(),
841 MessageDataType::UInt16 => size_of::<u16>(),
842 MessageDataType::UInt32 => size_of::<u32>(),
843 MessageDataType::UInt64 => size_of::<u64>(),
844 MessageDataType::UInt128 => size_of::<u128>(),
845 MessageDataType::Int8 => size_of::<i8>(),
846 MessageDataType::Int16 => size_of::<i16>(),
847 MessageDataType::Int32 => size_of::<i32>(),
848 MessageDataType::Int64 => size_of::<i64>(),
849 MessageDataType::Int128 => size_of::<i128>(),
850 MessageDataType::Bool => size_of::<bool>(),
851 MessageDataType::String => runtime_static_string_length(),
852 MessageDataType::Binary => runtime_static_hex_length(),
853 MessageDataType::NoData => 0,
854 }
855}
856
857#[allow(dead_code)]
859#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
860pub enum MessageClass {
861 Data,
863 Error,
865 Warning,
867}
868
869#[derive(Debug, Clone, PartialEq, Eq)]
878pub enum TelemetryError {
879 GenericError(Option<Arc<str>>),
881
882 InvalidType,
884
885 SizeMismatch { expected: usize, got: usize },
887
888 SizeMismatchError,
890
891 EmptyEndpoints,
893
894 TimestampInvalid,
896
897 MissingPayload,
899
900 HandlerError(&'static str),
902
903 BadArg,
905
906 PermissionDenied,
908
909 Pack(&'static str),
911
912 Unpack(&'static str),
914
915 Io(&'static str),
917
918 InvalidUtf8,
920
921 TypeMismatch { expected: usize, got: usize },
923
924 InvalidLinkId(&'static str),
926
927 PacketTooLarge(&'static str),
929}
930
931impl TelemetryError {
932 pub const fn to_error_code(&self) -> TelemetryErrorCode {
935 match self {
936 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
937 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
938 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
939 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
940 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
941 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
942 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
943 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
944 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
945 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
946 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
947 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
948 TelemetryError::Io(_) => TelemetryErrorCode::Io,
949 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
950 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
951 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
952 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
953 }
954 }
955}
956
957impl core::fmt::Display for TelemetryError {
959 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
960 core::fmt::Debug::fmt(self, f)
965 }
966}
967
968#[cfg(feature = "std")]
970impl std::error::Error for TelemetryError {
971 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
972 None
973 }
974}
975
976#[cfg(feature = "std")]
978impl From<Error> for TelemetryError {
979 fn from(error: Error) -> Self {
980 let str = error.to_string();
981 let astr: Arc<str> = Arc::from(str.as_str());
982 TelemetryError::GenericError(Some(astr))
983 }
984}
985
986#[cfg(feature = "std")]
988impl From<Box<dyn std::error::Error>> for TelemetryError {
989 fn from(err: Box<dyn std::error::Error>) -> Self {
990 let str = err.to_string();
991 let astr: Arc<str> = Arc::from(str.as_str());
992 TelemetryError::GenericError(Some(astr))
993 }
994}
995
996#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1001#[repr(i32)]
1002pub enum TelemetryErrorCode {
1003 GenericError = -2,
1004 InvalidType = -3,
1005 SizeMismatch = -4,
1006 SizeMismatchError = -5,
1007 EmptyEndpoints = -6,
1008 TimestampInvalid = -7,
1009 MissingPayload = -8,
1010 HandlerError = -9,
1011 BadArg = -10,
1012 PermissionDenied = -11,
1013 Pack = -12,
1014 Unpack = -13,
1015 Io = -14,
1016 InvalidUtf8 = -15,
1017 TypeMismatch = -16,
1018 InvalidLinkId = -17,
1019 PacketTooLarge = -18,
1020}
1021
1022impl_repr_i32_enum!(
1024 TelemetryErrorCode,
1025 TelemetryErrorCode::MAX,
1026 TelemetryErrorCode::MIN
1027);
1028
1029impl TelemetryErrorCode {
1030 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1032
1033 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1035
1036 #[inline]
1040 pub fn as_str(&self) -> &'static str {
1041 match self {
1042 TelemetryErrorCode::GenericError => "GenericError",
1043 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1044 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1045 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1046 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1047 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1048 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1049 TelemetryErrorCode::HandlerError => "{Handler Error}",
1050 TelemetryErrorCode::BadArg => "{Bad Arg}",
1051 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1052 TelemetryErrorCode::Pack => "{Pack Error}",
1053 TelemetryErrorCode::Unpack => "{Unpack Error}",
1054 TelemetryErrorCode::Io => "{IO Error}",
1055 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1056 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1057 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1058 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1059 }
1060 }
1061
1062 #[inline]
1070 pub fn try_from_i32(x: i32) -> Option<Self> {
1071 try_enum_from_i32(x)
1072 }
1073}
1074
1075pub type TelemetryResult<T> = Result<T, TelemetryError>;
1077
1078#[inline]
1090pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1091 if x > E::MAX {
1092 return None;
1093 }
1094 E::from_u32(x)
1095}
1096
1097#[inline]
1105pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1106 if x < E::MIN || x > E::MAX {
1107 return None;
1108 }
1109
1110 let e = unsafe { (&x as *const i32 as *const E).read() };
1112 Some(e)
1113}