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 varint;
193pub mod wire_format;
194pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
200
201pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
203
204pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
206
207impl ReprU32Enum for DataType {
208 const MAX: u32 = u32::MAX;
209
210 #[inline]
211 fn from_u32(x: u32) -> Option<Self> {
212 DataType::try_from_u32(x)
213 }
214}
215
216impl ReprU32Enum for DataEndpoint {
217 const MAX: u32 = u32::MAX;
218
219 #[inline]
220 fn from_u32(x: u32) -> Option<Self> {
221 DataEndpoint::try_from_u32(x)
222 }
223}
224
225#[inline]
226pub fn current_max_endpoint_id() -> u32 {
227 max_endpoint_id()
228}
229
230#[inline]
231pub fn current_max_data_type_id() -> u32 {
232 max_data_type_id()
233}
234
235#[repr(i32)]
236#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
237pub enum RouteSelectionMode {
238 Fanout = 0,
239 Weighted = 1,
240 Failover = 2,
241}
242
243impl_repr_i32_enum!(
244 RouteSelectionMode,
245 RouteSelectionMode::Fanout as i32,
246 RouteSelectionMode::Failover as i32
247);
248
249#[inline]
250const fn parse_usize(s: &str) -> usize {
251 let bytes = s.as_bytes();
252 let mut i = 0;
253 let mut val = 0;
254
255 while i < bytes.len() {
256 let c = bytes[i];
257 if c < b'0' || c > b'9' {
258 panic!("Invalid digit");
259 }
260 val = val * 10 + (c - b'0') as usize;
261 i += 1;
262 }
263 val
264}
265
266#[inline]
267pub const fn parse_f64(s: &str) -> f64 {
268 let bytes = s.as_bytes();
269 let mut i = 0;
270
271 if bytes.is_empty() {
272 panic!("empty string");
273 }
274
275 let mut sign = 1.0;
277 if bytes[i] == b'-' {
278 sign = -1.0;
279 i += 1;
280 } else if bytes[i] == b'+' {
281 i += 1;
282 }
283
284 let mut int_part: f64 = 0.0;
285 let mut has_digits = false;
286
287 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
288 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
289 i += 1;
290 has_digits = true;
291 }
292
293 let mut frac_part: f64 = 0.0;
294 let mut scale: f64 = 1.0;
295
296 if i < bytes.len() && bytes[i] == b'.' {
297 i += 1;
298
299 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
300 scale *= 10.0;
301 frac_part += (bytes[i] - b'0') as f64 / scale;
302 i += 1;
303 has_digits = true;
304 }
305 }
306
307 if !has_digits || i != bytes.len() {
308 panic!("invalid f64 literal");
309 }
310
311 sign * (int_part + frac_part)
312}
313
314#[inline(always)]
315const fn parse_strings(s: &str) -> &str {
316 s
317}
318
319#[inline]
320pub const fn parse_u8(s: &str) -> u8 {
321 let bytes = s.as_bytes();
322 let mut i = 0;
323 let mut val: u16 = 0;
324
325 if bytes.is_empty() {
326 panic!("empty string");
327 }
328
329 while i < bytes.len() {
330 let c = bytes[i];
331 if c < b'0' || c > b'9' {
332 panic!("invalid digit in u8");
333 }
334
335 val = val * 10 + (c - b'0') as u16;
336 if val > 255 {
337 panic!("u8 overflow");
338 }
339
340 i += 1;
341 }
342
343 val as u8
344}
345
346#[inline]
347pub const fn parse_u128(s: &str) -> u128 {
348 let bytes = s.as_bytes();
349 let mut i = 0;
350 let mut val: u128 = 0;
351
352 if bytes.is_empty() {
353 panic!("empty string");
354 }
355
356 while i < bytes.len() {
357 let c = bytes[i];
358 if c < b'0' || c > b'9' {
359 panic!("invalid digit in u128");
360 }
361
362 let digit = (c - b'0') as u128;
363
364 if val > (u128::MAX - digit) / 10 {
367 panic!("u128 overflow");
368 }
369
370 val = val * 10 + digit;
371 i += 1;
372 }
373
374 val
375}
376
377#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
381pub struct EndpointMeta {
382 #[cfg(feature = "std")]
384 name: Arc<str>,
385 #[cfg(not(feature = "std"))]
386 name: &'static str,
387 #[cfg(feature = "std")]
389 description: Arc<str>,
390 #[cfg(not(feature = "std"))]
391 description: &'static str,
392 link_local_only: bool,
394}
395
396impl EndpointMeta {
397 #[cfg(feature = "std")]
398 pub(crate) fn name_ref(&self) -> &str {
399 self.name.as_ref()
400 }
401
402 #[cfg(not(feature = "std"))]
403 pub(crate) fn name_ref(&self) -> &str {
404 self.name
405 }
406
407 #[cfg(feature = "std")]
408 pub(crate) fn description_ref(&self) -> &str {
409 self.description.as_ref()
410 }
411
412 #[cfg(not(feature = "std"))]
413 pub(crate) fn description_ref(&self) -> &str {
414 self.description
415 }
416
417 #[cfg(feature = "std")]
423 pub fn as_str(&self) -> Arc<str> {
424 self.name.clone()
425 }
426
427 #[cfg(not(feature = "std"))]
428 pub fn as_str(&self) -> &'static str {
429 self.name
430 }
431
432 #[inline]
434 #[cfg(feature = "std")]
435 pub fn description(&self) -> Arc<str> {
436 self.description.clone()
437 }
438
439 #[cfg(not(feature = "std"))]
440 pub fn description(&self) -> &'static str {
441 self.description
442 }
443
444 #[inline]
446 pub fn is_link_local_only(&self) -> bool {
447 self.link_local_only
448 }
449}
450
451impl DataEndpoint {
452 #[cfg(feature = "std")]
458 pub fn as_str(&self) -> Arc<str> {
459 get_endpoint_meta(*self).name
460 }
461
462 #[cfg(not(feature = "std"))]
463 pub fn as_str(&self) -> &'static str {
464 get_endpoint_meta(*self).name
465 }
466
467 #[cfg(feature = "std")]
469 pub fn description(&self) -> Arc<str> {
470 get_endpoint_meta(*self).description
471 }
472
473 #[cfg(not(feature = "std"))]
474 pub fn description(&self) -> &'static str {
475 get_endpoint_meta(*self).description
476 }
477
478 #[inline]
480 pub fn is_link_local_only(&self) -> bool {
481 get_endpoint_meta(*self).link_local_only
482 }
483}
484
485#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
487pub enum MessageElement {
488 Static(usize, MessageDataType, MessageClass),
492 Dynamic(MessageDataType, MessageClass),
496}
497
498impl MessageElement {
499 #[inline]
501 pub const fn data_type(&self) -> MessageDataType {
502 match self {
503 MessageElement::Static(_, dt, _) => *dt,
504 MessageElement::Dynamic(dt, _) => *dt,
505 }
506 }
507
508 #[inline]
510 pub const fn message_type(&self) -> MessageClass {
511 match self {
512 MessageElement::Static(_, _, mt) => *mt,
513 MessageElement::Dynamic(_, mt) => *mt,
514 }
515 }
516}
517
518#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
520#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
521pub enum ReliableMode {
522 #[cfg_attr(feature = "serde", serde(rename = "Off"))]
524 None,
525 Ordered,
527 Unordered,
529}
530
531#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
533pub enum E2eEncryptionPolicy {
534 PreferOff,
536 PreferOn,
538 RequireOn,
540}
541
542#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
544pub struct MessageMeta {
545 #[cfg(feature = "std")]
546 name: Arc<str>,
547 #[cfg(not(feature = "std"))]
548 name: &'static str,
549 #[cfg(feature = "std")]
551 description: Arc<str>,
552 #[cfg(not(feature = "std"))]
553 description: &'static str,
554 element: MessageElement,
556 #[cfg(feature = "std")]
558 endpoints: Arc<[DataEndpoint]>,
559 #[cfg(not(feature = "std"))]
560 endpoints: &'static [DataEndpoint],
561 reliable: ReliableMode,
563 priority: u8,
565 e2e_encryption: E2eEncryptionPolicy,
567}
568
569impl MessageMeta {
570 #[cfg(feature = "std")]
571 pub(crate) fn name_ref(&self) -> &str {
572 self.name.as_ref()
573 }
574
575 #[cfg(not(feature = "std"))]
576 pub(crate) fn name_ref(&self) -> &str {
577 self.name
578 }
579
580 #[cfg(feature = "std")]
581 pub(crate) fn description_ref(&self) -> &str {
582 self.description.as_ref()
583 }
584
585 #[cfg(not(feature = "std"))]
586 pub(crate) fn description_ref(&self) -> &str {
587 self.description
588 }
589
590 #[cfg(feature = "std")]
591 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
592 self.endpoints.as_ref()
593 }
594
595 #[cfg(not(feature = "std"))]
596 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
597 self.endpoints
598 }
599}
600
601impl DataType {
602 #[cfg(feature = "std")]
604 pub fn as_str(&self) -> Arc<str> {
605 get_message_meta(*self).name
606 }
607
608 #[cfg(not(feature = "std"))]
609 pub fn as_str(&self) -> &'static str {
610 get_message_meta(*self).name
611 }
612
613 #[cfg(feature = "std")]
615 pub fn description(&self) -> Arc<str> {
616 get_message_meta(*self).description
617 }
618
619 #[cfg(not(feature = "std"))]
620 pub fn description(&self) -> &'static str {
621 get_message_meta(*self).description
622 }
623}
624#[inline]
630pub fn message_meta(ty: DataType) -> MessageMeta {
631 get_message_meta(ty)
632}
633
634#[inline]
636pub fn is_reliable_type(ty: DataType) -> bool {
637 !matches!(get_message_meta(ty).reliable, ReliableMode::None)
638}
639
640#[inline]
642pub fn reliable_mode(ty: DataType) -> ReliableMode {
643 get_message_meta(ty).reliable
644}
645
646#[inline]
648pub fn message_priority(ty: DataType) -> u8 {
649 get_message_meta(ty).priority
650}
651
652#[inline]
660pub fn transport_priority(ty: DataType) -> u8 {
661 match ty {
662 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
665 255
666 }
667
668 DataType::DiscoveryAnnounce
670 | DataType::DiscoveryTimeSyncSources
671 | DataType::DiscoveryTopology
672 | DataType::DiscoveryTopologyRequest
673 | DataType::DiscoveryLeave
674 | DataType::DiscoveryLinkCapabilities
675 | DataType::DiscoveryAddress => 255,
676
677 DataType::DiscoverySchema
682 | DataType::DiscoverySchemaRequest
683 | DataType::ManagedVariableRequest
684 | DataType::ManagedVariableValue
685 | DataType::TimeSyncAnnounce
686 | DataType::TimeSyncRequest
687 | DataType::TimeSyncResponse => 254,
688
689 _ => message_priority(ty).min(253),
691 }
692}
693
694#[inline]
697pub(crate) fn small_frozen_control(
698 ty: DataType,
699 owners: usize,
700 shape: Option<MessageElement>,
701) -> bool {
702 if !(1..=3).contains(&owners) {
703 return false;
704 }
705 config::try_get_message_meta(ty).is_some_and(|meta| {
706 matches!(
707 meta.element,
708 MessageElement::Static(0..=16, MessageDataType::UInt8, _)
709 ) && matches!(
710 shape,
711 None | Some(MessageElement::Static(0..=16, MessageDataType::UInt8, _))
712 )
713 })
714}
715
716#[inline]
718pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
719 transport_priority(ty)
720}
721
722#[inline]
724pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
725 get_message_meta(ty).e2e_encryption
726}
727
728impl Mul<MessageElement> for usize {
731 type Output = usize;
732
733 #[inline]
734 fn mul(self, rhs: MessageElement) -> usize {
735 self * rhs.into()
736 }
737}
738
739impl Mul<usize> for MessageElement {
740 type Output = usize;
741
742 #[inline]
743 fn mul(self, rhs: usize) -> usize {
744 self.into() * rhs
745 }
746}
747
748impl MessageElement {
749 #[inline]
754 fn into(self) -> usize {
755 match self {
756 MessageElement::Static(a, _, _) => a,
757 _ => 0,
758 }
759 }
760}
761
762#[inline]
772pub fn get_needed_message_size(ty: DataType) -> usize {
773 data_type_size(get_data_type(ty)) * get_message_meta(ty).element
774}
775
776#[inline]
782pub fn get_info_type(ty: DataType) -> MessageClass {
783 get_message_meta(ty).element.message_type()
784}
785
786#[inline]
793pub fn get_data_type(ty: DataType) -> MessageDataType {
794 get_message_meta(ty).element.data_type()
795}
796
797#[inline]
803#[cfg(feature = "std")]
804pub fn get_message_name(ty: DataType) -> Arc<str> {
805 get_message_meta(ty).name
806}
807
808#[cfg(not(feature = "std"))]
809pub fn get_message_name(ty: DataType) -> &'static str {
810 get_message_meta(ty).name
811}
812
813#[inline]
819#[cfg(feature = "std")]
820pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
821 get_message_meta(ty).endpoints
822}
823
824#[cfg(not(feature = "std"))]
825pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
826 get_message_meta(ty).endpoints
827}
828
829#[allow(dead_code)]
834#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
835pub enum MessageDataType {
836 Float64,
837 Float32,
838 UInt8,
839 UInt16,
840 UInt32,
841 UInt64,
842 UInt128,
843 Int8,
844 Int16,
845 Int32,
846 Int64,
847 Int128,
848 Bool,
849 String,
850 Binary,
851 NoData,
852}
853
854#[inline]
863pub fn data_type_size(dt: MessageDataType) -> usize {
864 match dt {
865 MessageDataType::Float64 => size_of::<f64>(),
866 MessageDataType::Float32 => size_of::<f32>(),
867 MessageDataType::UInt8 => size_of::<u8>(),
868 MessageDataType::UInt16 => size_of::<u16>(),
869 MessageDataType::UInt32 => size_of::<u32>(),
870 MessageDataType::UInt64 => size_of::<u64>(),
871 MessageDataType::UInt128 => size_of::<u128>(),
872 MessageDataType::Int8 => size_of::<i8>(),
873 MessageDataType::Int16 => size_of::<i16>(),
874 MessageDataType::Int32 => size_of::<i32>(),
875 MessageDataType::Int64 => size_of::<i64>(),
876 MessageDataType::Int128 => size_of::<i128>(),
877 MessageDataType::Bool => size_of::<bool>(),
878 MessageDataType::String => runtime_static_string_length(),
879 MessageDataType::Binary => runtime_static_hex_length(),
880 MessageDataType::NoData => 0,
881 }
882}
883
884#[allow(dead_code)]
886#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
887pub enum MessageClass {
888 Data,
890 Error,
892 Warning,
894}
895
896#[derive(Debug, Clone, PartialEq, Eq)]
905pub enum TelemetryError {
906 GenericError(Option<Arc<str>>),
908
909 InvalidType,
911
912 SizeMismatch { expected: usize, got: usize },
914
915 SizeMismatchError,
917
918 EmptyEndpoints,
920
921 TimestampInvalid,
923
924 MissingPayload,
926
927 HandlerError(&'static str),
929
930 BadArg,
932
933 PermissionDenied,
935
936 Pack(&'static str),
938
939 Unpack(&'static str),
941
942 Io(&'static str),
944
945 InvalidUtf8,
947
948 TypeMismatch { expected: usize, got: usize },
950
951 InvalidLinkId(&'static str),
953
954 PacketTooLarge(&'static str),
956}
957
958impl TelemetryError {
959 pub const fn to_error_code(&self) -> TelemetryErrorCode {
962 match self {
963 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
964 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
965 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
966 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
967 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
968 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
969 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
970 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
971 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
972 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
973 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
974 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
975 TelemetryError::Io(_) => TelemetryErrorCode::Io,
976 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
977 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
978 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
979 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
980 }
981 }
982}
983
984impl core::fmt::Display for TelemetryError {
986 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
987 core::fmt::Debug::fmt(self, f)
992 }
993}
994
995#[cfg(feature = "std")]
997impl std::error::Error for TelemetryError {
998 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
999 None
1000 }
1001}
1002
1003#[cfg(feature = "std")]
1005impl From<Error> for TelemetryError {
1006 fn from(error: Error) -> Self {
1007 let str = error.to_string();
1008 let astr: Arc<str> = Arc::from(str.as_str());
1009 TelemetryError::GenericError(Some(astr))
1010 }
1011}
1012
1013#[cfg(feature = "std")]
1015impl From<Box<dyn std::error::Error>> for TelemetryError {
1016 fn from(err: Box<dyn std::error::Error>) -> Self {
1017 let str = err.to_string();
1018 let astr: Arc<str> = Arc::from(str.as_str());
1019 TelemetryError::GenericError(Some(astr))
1020 }
1021}
1022
1023#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1028#[repr(i32)]
1029pub enum TelemetryErrorCode {
1030 GenericError = -2,
1031 InvalidType = -3,
1032 SizeMismatch = -4,
1033 SizeMismatchError = -5,
1034 EmptyEndpoints = -6,
1035 TimestampInvalid = -7,
1036 MissingPayload = -8,
1037 HandlerError = -9,
1038 BadArg = -10,
1039 PermissionDenied = -11,
1040 Pack = -12,
1041 Unpack = -13,
1042 Io = -14,
1043 InvalidUtf8 = -15,
1044 TypeMismatch = -16,
1045 InvalidLinkId = -17,
1046 PacketTooLarge = -18,
1047}
1048
1049impl_repr_i32_enum!(
1051 TelemetryErrorCode,
1052 TelemetryErrorCode::MAX,
1053 TelemetryErrorCode::MIN
1054);
1055
1056impl TelemetryErrorCode {
1057 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1059
1060 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1062
1063 #[inline]
1067 pub fn as_str(&self) -> &'static str {
1068 match self {
1069 TelemetryErrorCode::GenericError => "GenericError",
1070 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1071 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1072 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1073 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1074 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1075 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1076 TelemetryErrorCode::HandlerError => "{Handler Error}",
1077 TelemetryErrorCode::BadArg => "{Bad Arg}",
1078 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1079 TelemetryErrorCode::Pack => "{Pack Error}",
1080 TelemetryErrorCode::Unpack => "{Unpack Error}",
1081 TelemetryErrorCode::Io => "{IO Error}",
1082 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1083 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1084 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1085 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1086 }
1087 }
1088
1089 #[inline]
1097 pub fn try_from_i32(x: i32) -> Option<Self> {
1098 try_enum_from_i32(x)
1099 }
1100}
1101
1102pub type TelemetryResult<T> = Result<T, TelemetryError>;
1104
1105#[inline]
1117pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1118 if x > E::MAX {
1119 return None;
1120 }
1121 E::from_u32(x)
1122}
1123
1124#[inline]
1132pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1133 if x < E::MIN || x > E::MAX {
1134 return None;
1135 }
1136
1137 let e = unsafe { (&x as *const i32 as *const E).read() };
1139 Some(e)
1140}