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::string::ToString;
48use alloc::sync::Arc;
49use core::fmt::Formatter;
50use core::mem::size_of;
51use core::ops::Mul;
52
53#[cfg(all(test, feature = "std"))]
58mod tests;
59
60#[cfg(feature = "python")]
61#[cfg(feature = "std")]
62mod python_api;
63
64#[cfg(all(not(feature = "std"), target_os = "none"))]
72unsafe extern "C" {
73 fn seds_error_msg(msg: *const u8, len: usize);
74}
75
76#[cfg(all(not(feature = "std"), target_os = "none"))]
77mod embedded_alloc {
78 use core::alloc::{GlobalAlloc, Layout};
79 use core::mem::size_of;
80
81 unsafe extern "C" {
82 fn telemetryMalloc(size: usize) -> *mut core::ffi::c_void;
83 fn telemetryFree(ptr: *mut core::ffi::c_void);
84 fn telemetry_panic_hook(msg: *const u8, len: usize);
85 }
86
87 struct TelemetryAlloc;
90
91 #[inline]
92 fn align_up(addr: usize, align: usize) -> usize {
93 (addr + (align - 1)) & !(align - 1)
94 }
95
96 unsafe impl GlobalAlloc for TelemetryAlloc {
97 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
98 let align = layout.align().max(size_of::<usize>());
99 let header = size_of::<usize>();
100 let total = match layout
101 .size()
102 .checked_add(align)
103 .and_then(|v| v.checked_add(header))
104 {
105 Some(v) => v,
106 None => return core::ptr::null_mut(),
107 };
108
109 let raw = unsafe { telemetryMalloc(total) as *mut u8 };
110 if raw.is_null() {
111 return core::ptr::null_mut();
112 }
113
114 let base = raw as usize + header;
115 let aligned = align_up(base, align) as *mut u8;
116
117 unsafe {
119 let slot = (aligned as *mut usize).offset(-1);
120 *slot = raw as usize;
121 }
122
123 aligned
124 }
125
126 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
127 if ptr.is_null() {
128 return;
129 }
130
131 let raw = unsafe {
132 let slot = (ptr as *mut usize).offset(-1);
133 *slot as *mut core::ffi::c_void
134 };
135 unsafe { telemetryFree(raw) };
136 }
137 }
138
139 #[global_allocator]
140 static A: TelemetryAlloc = TelemetryAlloc;
141
142 use core::panic::PanicInfo;
144
145 #[panic_handler]
146 fn panic(_info: &PanicInfo) -> ! {
147 let msg = b"rust panic";
148 unsafe {
149 telemetry_panic_hook(msg.as_ptr(), msg.len());
150 }
151
152 loop {}
154 }
155
156 }
159
160mod 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 packet;
177mod queue;
178pub mod relay;
179pub mod router;
180mod small_payload;
181#[cfg(feature = "timesync")]
182pub mod timesync;
183pub mod wire_format;
184pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
190
191pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
193
194pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
196
197impl ReprU32Enum for DataType {
198 const MAX: u32 = MAX_VALUE_DATA_TYPE;
199
200 #[inline]
201 fn from_u32(x: u32) -> Option<Self> {
202 DataType::try_from_u32(x)
203 }
204}
205
206impl ReprU32Enum for DataEndpoint {
207 const MAX: u32 = MAX_VALUE_DATA_ENDPOINT;
208
209 #[inline]
210 fn from_u32(x: u32) -> Option<Self> {
211 DataEndpoint::try_from_u32(x)
212 }
213}
214
215#[inline]
216pub fn current_max_endpoint_id() -> u32 {
217 max_endpoint_id()
218}
219
220#[inline]
221pub fn current_max_data_type_id() -> u32 {
222 max_data_type_id()
223}
224
225#[repr(i32)]
226#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
227pub enum RouteSelectionMode {
228 Fanout = 0,
229 Weighted = 1,
230 Failover = 2,
231}
232
233impl_repr_i32_enum!(
234 RouteSelectionMode,
235 RouteSelectionMode::Fanout as i32,
236 RouteSelectionMode::Failover as i32
237);
238
239#[inline]
240const fn parse_usize(s: &str) -> usize {
241 let bytes = s.as_bytes();
242 let mut i = 0;
243 let mut val = 0;
244
245 while i < bytes.len() {
246 let c = bytes[i];
247 if c < b'0' || c > b'9' {
248 panic!("Invalid digit");
249 }
250 val = val * 10 + (c - b'0') as usize;
251 i += 1;
252 }
253 val
254}
255
256#[inline]
257pub const fn parse_f64(s: &str) -> f64 {
258 let bytes = s.as_bytes();
259 let mut i = 0;
260
261 if bytes.is_empty() {
262 panic!("empty string");
263 }
264
265 let mut sign = 1.0;
267 if bytes[i] == b'-' {
268 sign = -1.0;
269 i += 1;
270 } else if bytes[i] == b'+' {
271 i += 1;
272 }
273
274 let mut int_part: f64 = 0.0;
275 let mut has_digits = false;
276
277 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
278 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
279 i += 1;
280 has_digits = true;
281 }
282
283 let mut frac_part: f64 = 0.0;
284 let mut scale: f64 = 1.0;
285
286 if i < bytes.len() && bytes[i] == b'.' {
287 i += 1;
288
289 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
290 scale *= 10.0;
291 frac_part += (bytes[i] - b'0') as f64 / scale;
292 i += 1;
293 has_digits = true;
294 }
295 }
296
297 if !has_digits || i != bytes.len() {
298 panic!("invalid f64 literal");
299 }
300
301 sign * (int_part + frac_part)
302}
303
304#[inline(always)]
305const fn parse_strings(s: &str) -> &str {
306 s
307}
308
309#[inline]
310pub const fn parse_u8(s: &str) -> u8 {
311 let bytes = s.as_bytes();
312 let mut i = 0;
313 let mut val: u16 = 0;
314
315 if bytes.is_empty() {
316 panic!("empty string");
317 }
318
319 while i < bytes.len() {
320 let c = bytes[i];
321 if c < b'0' || c > b'9' {
322 panic!("invalid digit in u8");
323 }
324
325 val = val * 10 + (c - b'0') as u16;
326 if val > 255 {
327 panic!("u8 overflow");
328 }
329
330 i += 1;
331 }
332
333 val as u8
334}
335
336#[inline]
337pub const fn parse_u128(s: &str) -> u128 {
338 let bytes = s.as_bytes();
339 let mut i = 0;
340 let mut val: u128 = 0;
341
342 if bytes.is_empty() {
343 panic!("empty string");
344 }
345
346 while i < bytes.len() {
347 let c = bytes[i];
348 if c < b'0' || c > b'9' {
349 panic!("invalid digit in u128");
350 }
351
352 let digit = (c - b'0') as u128;
353
354 if val > (u128::MAX - digit) / 10 {
357 panic!("u128 overflow");
358 }
359
360 val = val * 10 + digit;
361 i += 1;
362 }
363
364 val
365}
366
367#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
371pub struct EndpointMeta {
372 #[cfg(feature = "std")]
374 name: Arc<str>,
375 #[cfg(not(feature = "std"))]
376 name: &'static str,
377 #[cfg(feature = "std")]
379 description: Arc<str>,
380 #[cfg(not(feature = "std"))]
381 description: &'static str,
382 link_local_only: bool,
384}
385
386impl EndpointMeta {
387 #[cfg(feature = "std")]
388 pub(crate) fn name_ref(&self) -> &str {
389 self.name.as_ref()
390 }
391
392 #[cfg(not(feature = "std"))]
393 pub(crate) fn name_ref(&self) -> &str {
394 self.name
395 }
396
397 #[cfg(feature = "std")]
398 pub(crate) fn description_ref(&self) -> &str {
399 self.description.as_ref()
400 }
401
402 #[cfg(not(feature = "std"))]
403 pub(crate) fn description_ref(&self) -> &str {
404 self.description
405 }
406
407 #[cfg(feature = "std")]
413 pub fn as_str(&self) -> Arc<str> {
414 self.name.clone()
415 }
416
417 #[cfg(not(feature = "std"))]
418 pub fn as_str(&self) -> &'static str {
419 self.name
420 }
421
422 #[inline]
424 #[cfg(feature = "std")]
425 pub fn description(&self) -> Arc<str> {
426 self.description.clone()
427 }
428
429 #[cfg(not(feature = "std"))]
430 pub fn description(&self) -> &'static str {
431 self.description
432 }
433
434 #[inline]
436 pub fn is_link_local_only(&self) -> bool {
437 self.link_local_only
438 }
439}
440
441impl DataEndpoint {
442 #[cfg(feature = "std")]
448 pub fn as_str(&self) -> Arc<str> {
449 get_endpoint_meta(*self).name
450 }
451
452 #[cfg(not(feature = "std"))]
453 pub fn as_str(&self) -> &'static str {
454 get_endpoint_meta(*self).name
455 }
456
457 #[cfg(feature = "std")]
459 pub fn description(&self) -> Arc<str> {
460 get_endpoint_meta(*self).description
461 }
462
463 #[cfg(not(feature = "std"))]
464 pub fn description(&self) -> &'static str {
465 get_endpoint_meta(*self).description
466 }
467
468 #[inline]
470 pub fn is_link_local_only(&self) -> bool {
471 get_endpoint_meta(*self).link_local_only
472 }
473}
474
475#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
477pub enum MessageElement {
478 Static(usize, MessageDataType, MessageClass),
482 Dynamic(MessageDataType, MessageClass),
486}
487
488impl MessageElement {
489 #[inline]
491 pub const fn data_type(&self) -> MessageDataType {
492 match self {
493 MessageElement::Static(_, dt, _) => *dt,
494 MessageElement::Dynamic(dt, _) => *dt,
495 }
496 }
497
498 #[inline]
500 pub const fn message_type(&self) -> MessageClass {
501 match self {
502 MessageElement::Static(_, _, mt) => *mt,
503 MessageElement::Dynamic(_, mt) => *mt,
504 }
505 }
506}
507
508#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
510pub enum ReliableMode {
511 None,
513 Ordered,
515 Unordered,
517}
518
519#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
521pub enum E2eEncryptionPolicy {
522 PreferOff,
524 PreferOn,
526 RequireOn,
528}
529
530#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
532pub struct MessageMeta {
533 #[cfg(feature = "std")]
534 name: Arc<str>,
535 #[cfg(not(feature = "std"))]
536 name: &'static str,
537 #[cfg(feature = "std")]
539 description: Arc<str>,
540 #[cfg(not(feature = "std"))]
541 description: &'static str,
542 element: MessageElement,
544 #[cfg(feature = "std")]
546 endpoints: Arc<[DataEndpoint]>,
547 #[cfg(not(feature = "std"))]
548 endpoints: &'static [DataEndpoint],
549 reliable: ReliableMode,
551 priority: u8,
553 e2e_encryption: E2eEncryptionPolicy,
555}
556
557impl MessageMeta {
558 #[cfg(feature = "std")]
559 pub(crate) fn name_ref(&self) -> &str {
560 self.name.as_ref()
561 }
562
563 #[cfg(not(feature = "std"))]
564 pub(crate) fn name_ref(&self) -> &str {
565 self.name
566 }
567
568 #[cfg(feature = "std")]
569 pub(crate) fn description_ref(&self) -> &str {
570 self.description.as_ref()
571 }
572
573 #[cfg(not(feature = "std"))]
574 pub(crate) fn description_ref(&self) -> &str {
575 self.description
576 }
577
578 #[cfg(feature = "std")]
579 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
580 self.endpoints.as_ref()
581 }
582
583 #[cfg(not(feature = "std"))]
584 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
585 self.endpoints
586 }
587}
588
589impl DataType {
590 #[cfg(feature = "std")]
592 pub fn as_str(&self) -> Arc<str> {
593 get_message_meta(*self).name
594 }
595
596 #[cfg(not(feature = "std"))]
597 pub fn as_str(&self) -> &'static str {
598 get_message_meta(*self).name
599 }
600
601 #[cfg(feature = "std")]
603 pub fn description(&self) -> Arc<str> {
604 get_message_meta(*self).description
605 }
606
607 #[cfg(not(feature = "std"))]
608 pub fn description(&self) -> &'static str {
609 get_message_meta(*self).description
610 }
611}
612#[inline]
618pub fn message_meta(ty: DataType) -> MessageMeta {
619 get_message_meta(ty)
620}
621
622#[inline]
624pub fn is_reliable_type(ty: DataType) -> bool {
625 !matches!(get_message_meta(ty).reliable, ReliableMode::None)
626}
627
628#[inline]
630pub fn reliable_mode(ty: DataType) -> ReliableMode {
631 get_message_meta(ty).reliable
632}
633
634#[inline]
636pub fn message_priority(ty: DataType) -> u8 {
637 get_message_meta(ty).priority
638}
639
640#[inline]
648pub fn transport_priority(ty: DataType) -> u8 {
649 match ty {
650 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
653 255
654 }
655
656 DataType::DiscoveryAnnounce
658 | DataType::DiscoveryTimeSyncSources
659 | DataType::DiscoveryTopology
660 | DataType::DiscoveryTopologyRequest
661 | DataType::DiscoveryLeave
662 | DataType::DiscoveryLinkCapabilities
663 | DataType::DiscoveryAddress => 255,
664
665 DataType::DiscoverySchema
670 | DataType::DiscoverySchemaRequest
671 | DataType::ManagedVariableRequest
672 | DataType::ManagedVariableValue
673 | DataType::TimeSyncAnnounce
674 | DataType::TimeSyncRequest
675 | DataType::TimeSyncResponse => 254,
676
677 _ => message_priority(ty).min(253),
679 }
680}
681
682#[inline]
685pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
686 transport_priority(ty)
687}
688
689#[inline]
691pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
692 get_message_meta(ty).e2e_encryption
693}
694
695impl Mul<MessageElement> for usize {
698 type Output = usize;
699
700 #[inline]
701 fn mul(self, rhs: MessageElement) -> usize {
702 self * rhs.into()
703 }
704}
705
706impl Mul<usize> for MessageElement {
707 type Output = usize;
708
709 #[inline]
710 fn mul(self, rhs: usize) -> usize {
711 self.into() * rhs
712 }
713}
714
715impl MessageElement {
716 #[inline]
721 fn into(self) -> usize {
722 match self {
723 MessageElement::Static(a, _, _) => a,
724 _ => 0,
725 }
726 }
727}
728
729#[inline]
739pub fn get_needed_message_size(ty: DataType) -> usize {
740 data_type_size(get_data_type(ty)) * get_message_meta(ty).element
741}
742
743#[inline]
749pub fn get_info_type(ty: DataType) -> MessageClass {
750 get_message_meta(ty).element.message_type()
751}
752
753#[inline]
760pub fn get_data_type(ty: DataType) -> MessageDataType {
761 get_message_meta(ty).element.data_type()
762}
763
764#[inline]
770#[cfg(feature = "std")]
771pub fn get_message_name(ty: DataType) -> Arc<str> {
772 get_message_meta(ty).name
773}
774
775#[cfg(not(feature = "std"))]
776pub fn get_message_name(ty: DataType) -> &'static str {
777 get_message_meta(ty).name
778}
779
780#[inline]
786#[cfg(feature = "std")]
787pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
788 get_message_meta(ty).endpoints
789}
790
791#[cfg(not(feature = "std"))]
792pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
793 get_message_meta(ty).endpoints
794}
795
796#[allow(dead_code)]
801#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
802pub enum MessageDataType {
803 Float64,
804 Float32,
805 UInt8,
806 UInt16,
807 UInt32,
808 UInt64,
809 UInt128,
810 Int8,
811 Int16,
812 Int32,
813 Int64,
814 Int128,
815 Bool,
816 String,
817 Binary,
818 NoData,
819}
820
821#[inline]
830pub fn data_type_size(dt: MessageDataType) -> usize {
831 match dt {
832 MessageDataType::Float64 => size_of::<f64>(),
833 MessageDataType::Float32 => size_of::<f32>(),
834 MessageDataType::UInt8 => size_of::<u8>(),
835 MessageDataType::UInt16 => size_of::<u16>(),
836 MessageDataType::UInt32 => size_of::<u32>(),
837 MessageDataType::UInt64 => size_of::<u64>(),
838 MessageDataType::UInt128 => size_of::<u128>(),
839 MessageDataType::Int8 => size_of::<i8>(),
840 MessageDataType::Int16 => size_of::<i16>(),
841 MessageDataType::Int32 => size_of::<i32>(),
842 MessageDataType::Int64 => size_of::<i64>(),
843 MessageDataType::Int128 => size_of::<i128>(),
844 MessageDataType::Bool => size_of::<bool>(),
845 MessageDataType::String => runtime_static_string_length(),
846 MessageDataType::Binary => runtime_static_hex_length(),
847 MessageDataType::NoData => 0,
848 }
849}
850
851#[allow(dead_code)]
853#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
854pub enum MessageClass {
855 Data,
857 Error,
859 Warning,
861}
862
863#[derive(Debug, Clone, PartialEq, Eq)]
872pub enum TelemetryError {
873 GenericError(Option<Arc<str>>),
875
876 InvalidType,
878
879 SizeMismatch { expected: usize, got: usize },
881
882 SizeMismatchError,
884
885 EmptyEndpoints,
887
888 TimestampInvalid,
890
891 MissingPayload,
893
894 HandlerError(&'static str),
896
897 BadArg,
899
900 PermissionDenied,
902
903 Pack(&'static str),
905
906 Unpack(&'static str),
908
909 Io(&'static str),
911
912 InvalidUtf8,
914
915 TypeMismatch { expected: usize, got: usize },
917
918 InvalidLinkId(&'static str),
920
921 PacketTooLarge(&'static str),
923}
924
925impl TelemetryError {
926 pub const fn to_error_code(&self) -> TelemetryErrorCode {
929 match self {
930 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
931 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
932 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
933 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
934 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
935 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
936 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
937 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
938 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
939 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
940 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
941 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
942 TelemetryError::Io(_) => TelemetryErrorCode::Io,
943 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
944 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
945 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
946 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
947 }
948 }
949}
950
951impl core::fmt::Display for TelemetryError {
953 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
954 f.write_str(&TelemetryError::to_string(self))
955 }
956}
957
958#[cfg(feature = "std")]
960impl std::error::Error for TelemetryError {
961 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
962 None
963 }
964}
965
966#[cfg(feature = "std")]
968impl From<Error> for TelemetryError {
969 fn from(error: Error) -> Self {
970 let str = error.to_string();
971 let astr: Arc<str> = Arc::from(str.as_str());
972 TelemetryError::GenericError(Some(astr))
973 }
974}
975
976#[cfg(feature = "std")]
978impl From<Box<dyn std::error::Error>> for TelemetryError {
979 fn from(err: Box<dyn std::error::Error>) -> Self {
980 let str = err.to_string();
981 let astr: Arc<str> = Arc::from(str.as_str());
982 TelemetryError::GenericError(Some(astr))
983 }
984}
985
986#[derive(Debug, Clone, Copy, PartialEq, Eq)]
991#[repr(i32)]
992pub enum TelemetryErrorCode {
993 GenericError = -2,
994 InvalidType = -3,
995 SizeMismatch = -4,
996 SizeMismatchError = -5,
997 EmptyEndpoints = -6,
998 TimestampInvalid = -7,
999 MissingPayload = -8,
1000 HandlerError = -9,
1001 BadArg = -10,
1002 PermissionDenied = -11,
1003 Pack = -12,
1004 Unpack = -13,
1005 Io = -14,
1006 InvalidUtf8 = -15,
1007 TypeMismatch = -16,
1008 InvalidLinkId = -17,
1009 PacketTooLarge = -18,
1010}
1011
1012impl_repr_i32_enum!(
1014 TelemetryErrorCode,
1015 TelemetryErrorCode::MAX,
1016 TelemetryErrorCode::MIN
1017);
1018
1019impl TelemetryErrorCode {
1020 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1022
1023 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1025
1026 #[inline]
1030 pub fn as_str(&self) -> &'static str {
1031 match self {
1032 TelemetryErrorCode::GenericError => "GenericError",
1033 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1034 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1035 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1036 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1037 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1038 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1039 TelemetryErrorCode::HandlerError => "{Handler Error}",
1040 TelemetryErrorCode::BadArg => "{Bad Arg}",
1041 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1042 TelemetryErrorCode::Pack => "{Pack Error}",
1043 TelemetryErrorCode::Unpack => "{Unpack Error}",
1044 TelemetryErrorCode::Io => "{IO Error}",
1045 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1046 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1047 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1048 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1049 }
1050 }
1051
1052 #[inline]
1060 pub fn try_from_i32(x: i32) -> Option<Self> {
1061 try_enum_from_i32(x)
1062 }
1063}
1064
1065pub type TelemetryResult<T> = Result<T, TelemetryError>;
1067
1068#[inline]
1080pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1081 if x > E::MAX {
1082 return None;
1083 }
1084 E::from_u32(x)
1085}
1086
1087#[inline]
1095pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1096 if x < E::MIN || x > E::MAX {
1097 return None;
1098 }
1099
1100 let e = unsafe { (&x as *const i32 as *const E).read() };
1102 Some(e)
1103}