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;
180#[cfg(feature = "compression")]
181mod payload_codec;
182mod shared_bytes;
183pub use shared_bytes::SharedBytes;
184#[cfg(feature = "compact-packet-store")]
185pub mod packet_store;
186mod queue;
187pub mod relay;
188pub mod router;
189pub mod routing_config;
190mod side_transport;
191#[cfg(any(test, all(feature = "embedded", not(feature = "std"))))]
192mod small_map;
193mod small_payload;
194mod small_sort;
195#[cfg(feature = "timesync")]
196pub mod timesync;
197mod type_stats;
198mod varint;
199pub mod wire_format;
200pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
206
207pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
209
210pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
212
213impl ReprU32Enum for DataType {
214 const MAX: u32 = u32::MAX;
215
216 #[inline]
217 fn from_u32(x: u32) -> Option<Self> {
218 DataType::try_from_u32(x)
219 }
220}
221
222impl ReprU32Enum for DataEndpoint {
223 const MAX: u32 = u32::MAX;
224
225 #[inline]
226 fn from_u32(x: u32) -> Option<Self> {
227 DataEndpoint::try_from_u32(x)
228 }
229}
230
231#[inline]
232pub fn current_max_endpoint_id() -> u32 {
233 max_endpoint_id()
234}
235
236#[inline]
237pub fn current_max_data_type_id() -> u32 {
238 max_data_type_id()
239}
240
241#[repr(i32)]
242#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
243pub enum RouteSelectionMode {
244 Fanout = 0,
245 Weighted = 1,
246 Failover = 2,
247}
248
249impl_repr_i32_enum!(
250 RouteSelectionMode,
251 RouteSelectionMode::Fanout as i32,
252 RouteSelectionMode::Failover as i32
253);
254
255#[inline]
256const fn parse_usize(s: &str) -> usize {
257 let bytes = s.as_bytes();
258 let mut i = 0;
259 let mut val = 0;
260
261 while i < bytes.len() {
262 let c = bytes[i];
263 if c < b'0' || c > b'9' {
264 panic!("Invalid digit");
265 }
266 val = val * 10 + (c - b'0') as usize;
267 i += 1;
268 }
269 val
270}
271
272#[inline]
273pub const fn parse_f64(s: &str) -> f64 {
274 let bytes = s.as_bytes();
275 let mut i = 0;
276
277 if bytes.is_empty() {
278 panic!("empty string");
279 }
280
281 let mut sign = 1.0;
283 if bytes[i] == b'-' {
284 sign = -1.0;
285 i += 1;
286 } else if bytes[i] == b'+' {
287 i += 1;
288 }
289
290 let mut int_part: f64 = 0.0;
291 let mut has_digits = false;
292
293 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
294 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
295 i += 1;
296 has_digits = true;
297 }
298
299 let mut frac_part: f64 = 0.0;
300 let mut scale: f64 = 1.0;
301
302 if i < bytes.len() && bytes[i] == b'.' {
303 i += 1;
304
305 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
306 scale *= 10.0;
307 frac_part += (bytes[i] - b'0') as f64 / scale;
308 i += 1;
309 has_digits = true;
310 }
311 }
312
313 if !has_digits || i != bytes.len() {
314 panic!("invalid f64 literal");
315 }
316
317 sign * (int_part + frac_part)
318}
319
320#[inline(always)]
321const fn parse_strings(s: &str) -> &str {
322 s
323}
324
325#[inline]
326pub const fn parse_u8(s: &str) -> u8 {
327 let bytes = s.as_bytes();
328 let mut i = 0;
329 let mut val: u16 = 0;
330
331 if bytes.is_empty() {
332 panic!("empty string");
333 }
334
335 while i < bytes.len() {
336 let c = bytes[i];
337 if c < b'0' || c > b'9' {
338 panic!("invalid digit in u8");
339 }
340
341 val = val * 10 + (c - b'0') as u16;
342 if val > 255 {
343 panic!("u8 overflow");
344 }
345
346 i += 1;
347 }
348
349 val as u8
350}
351
352#[inline]
353pub const fn parse_u128(s: &str) -> u128 {
354 let bytes = s.as_bytes();
355 let mut i = 0;
356 let mut val: u128 = 0;
357
358 if bytes.is_empty() {
359 panic!("empty string");
360 }
361
362 while i < bytes.len() {
363 let c = bytes[i];
364 if c < b'0' || c > b'9' {
365 panic!("invalid digit in u128");
366 }
367
368 let digit = (c - b'0') as u128;
369
370 if val > (u128::MAX - digit) / 10 {
373 panic!("u128 overflow");
374 }
375
376 val = val * 10 + digit;
377 i += 1;
378 }
379
380 val
381}
382
383#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
387pub struct EndpointMeta {
388 #[cfg(feature = "std")]
390 name: Arc<str>,
391 #[cfg(not(feature = "std"))]
392 name: &'static str,
393 #[cfg(feature = "std")]
395 description: Arc<str>,
396 #[cfg(not(feature = "std"))]
397 description: &'static str,
398 link_local_only: bool,
400}
401
402impl EndpointMeta {
403 #[cfg(feature = "std")]
404 pub(crate) fn name_ref(&self) -> &str {
405 self.name.as_ref()
406 }
407
408 #[cfg(not(feature = "std"))]
409 pub(crate) fn name_ref(&self) -> &str {
410 self.name
411 }
412
413 #[cfg(feature = "std")]
414 pub(crate) fn description_ref(&self) -> &str {
415 self.description.as_ref()
416 }
417
418 #[cfg(not(feature = "std"))]
419 pub(crate) fn description_ref(&self) -> &str {
420 self.description
421 }
422
423 #[cfg(feature = "std")]
429 pub fn as_str(&self) -> Arc<str> {
430 self.name.clone()
431 }
432
433 #[cfg(not(feature = "std"))]
434 pub fn as_str(&self) -> &'static str {
435 self.name
436 }
437
438 #[inline]
440 #[cfg(feature = "std")]
441 pub fn description(&self) -> Arc<str> {
442 self.description.clone()
443 }
444
445 #[cfg(not(feature = "std"))]
446 pub fn description(&self) -> &'static str {
447 self.description
448 }
449
450 #[inline]
452 pub fn is_link_local_only(&self) -> bool {
453 self.link_local_only
454 }
455}
456
457impl DataEndpoint {
458 #[cfg(feature = "std")]
464 pub fn as_str(&self) -> Arc<str> {
465 get_endpoint_meta(*self).name
466 }
467
468 #[cfg(not(feature = "std"))]
469 pub fn as_str(&self) -> &'static str {
470 get_endpoint_meta(*self).name
471 }
472
473 #[cfg(feature = "std")]
475 pub fn description(&self) -> Arc<str> {
476 get_endpoint_meta(*self).description
477 }
478
479 #[cfg(not(feature = "std"))]
480 pub fn description(&self) -> &'static str {
481 get_endpoint_meta(*self).description
482 }
483
484 #[inline]
486 pub fn is_link_local_only(&self) -> bool {
487 get_endpoint_meta(*self).link_local_only
488 }
489}
490
491#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
493pub enum MessageElement {
494 Static(usize, MessageDataType, MessageClass),
498 Dynamic(MessageDataType, MessageClass),
502}
503
504impl MessageElement {
505 #[inline]
507 pub const fn data_type(&self) -> MessageDataType {
508 match self {
509 MessageElement::Static(_, dt, _) => *dt,
510 MessageElement::Dynamic(dt, _) => *dt,
511 }
512 }
513
514 #[inline]
516 pub const fn message_type(&self) -> MessageClass {
517 match self {
518 MessageElement::Static(_, _, mt) => *mt,
519 MessageElement::Dynamic(_, mt) => *mt,
520 }
521 }
522}
523
524#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
526#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
527pub enum ReliableMode {
528 #[cfg_attr(feature = "serde", serde(rename = "Off"))]
530 None,
531 Ordered,
533 Unordered,
535}
536
537#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
539pub enum E2eEncryptionPolicy {
540 PreferOff,
542 PreferOn,
544 RequireOn,
546}
547
548#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
550pub struct MessageMeta {
551 #[cfg(feature = "std")]
552 name: Arc<str>,
553 #[cfg(not(feature = "std"))]
554 name: &'static str,
555 #[cfg(feature = "std")]
557 description: Arc<str>,
558 #[cfg(not(feature = "std"))]
559 description: &'static str,
560 element: MessageElement,
562 #[cfg(feature = "std")]
564 endpoints: Arc<[DataEndpoint]>,
565 #[cfg(not(feature = "std"))]
566 endpoints: &'static [DataEndpoint],
567 reliable: ReliableMode,
569 priority: u8,
571 e2e_encryption: E2eEncryptionPolicy,
573}
574
575impl MessageMeta {
576 pub(crate) fn endpoints_owned(&self) -> Arc<[DataEndpoint]> {
577 #[cfg(feature = "std")]
578 {
579 self.endpoints.clone()
580 }
581 #[cfg(not(feature = "std"))]
582 {
583 Arc::from(self.endpoints)
584 }
585 }
586
587 #[cfg(feature = "std")]
588 pub(crate) fn name_ref(&self) -> &str {
589 self.name.as_ref()
590 }
591
592 #[cfg(not(feature = "std"))]
593 pub(crate) fn name_ref(&self) -> &str {
594 self.name
595 }
596
597 #[cfg(feature = "std")]
598 pub(crate) fn description_ref(&self) -> &str {
599 self.description.as_ref()
600 }
601
602 #[cfg(not(feature = "std"))]
603 pub(crate) fn description_ref(&self) -> &str {
604 self.description
605 }
606
607 #[cfg(feature = "std")]
608 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
609 self.endpoints.as_ref()
610 }
611
612 #[cfg(not(feature = "std"))]
613 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
614 self.endpoints
615 }
616}
617
618impl DataType {
619 #[cfg(feature = "std")]
621 pub fn as_str(&self) -> Arc<str> {
622 get_message_meta(*self).name
623 }
624
625 #[cfg(not(feature = "std"))]
626 pub fn as_str(&self) -> &'static str {
627 get_message_meta(*self).name
628 }
629
630 #[cfg(feature = "std")]
632 pub fn description(&self) -> Arc<str> {
633 get_message_meta(*self).description
634 }
635
636 #[cfg(not(feature = "std"))]
637 pub fn description(&self) -> &'static str {
638 get_message_meta(*self).description
639 }
640}
641#[inline]
647pub fn message_meta(ty: DataType) -> MessageMeta {
648 get_message_meta(ty)
649}
650
651#[inline]
653pub fn is_reliable_type(ty: DataType) -> bool {
654 !matches!(reliable_mode(ty), ReliableMode::None)
655}
656
657#[inline]
659pub fn reliable_mode(ty: DataType) -> ReliableMode {
660 config::message_delivery_meta(ty).0
661}
662
663#[inline]
665pub fn message_priority(ty: DataType) -> u8 {
666 config::message_delivery_meta(ty).1
667}
668
669#[inline]
677pub fn transport_priority(ty: DataType) -> u8 {
678 match ty {
679 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
682 255
683 }
684
685 DataType::DiscoveryAnnounce
687 | DataType::DiscoveryTimeSyncSources
688 | DataType::DiscoveryTopology
689 | DataType::DiscoveryTopologyRequest
690 | DataType::DiscoveryLeave
691 | DataType::DiscoveryLinkCapabilities
692 | DataType::DiscoveryAddress => 255,
693
694 DataType::DiscoverySchema
699 | DataType::DiscoverySchemaRequest
700 | DataType::ManagedVariableRequest
701 | DataType::ManagedVariableValue
702 | DataType::TimeSyncAnnounce
703 | DataType::TimeSyncRequest
704 | DataType::TimeSyncResponse => 254,
705
706 _ => message_priority(ty).min(253),
708 }
709}
710
711#[inline]
714pub(crate) fn small_frozen_control(
715 ty: DataType,
716 owners: usize,
717 shape: Option<MessageElement>,
718) -> bool {
719 if !(1..=3).contains(&owners) {
720 return false;
721 }
722 config::try_get_message_meta(ty).is_some_and(|meta| {
723 matches!(
724 meta.element,
725 MessageElement::Static(0..=16, MessageDataType::UInt8, _)
726 ) && matches!(
727 shape,
728 None | Some(MessageElement::Static(0..=16, MessageDataType::UInt8, _))
729 )
730 })
731}
732
733#[inline]
735pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
736 transport_priority(ty)
737}
738
739#[inline]
741pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
742 get_message_meta(ty).e2e_encryption
743}
744
745impl Mul<MessageElement> for usize {
748 type Output = usize;
749
750 #[inline]
751 fn mul(self, rhs: MessageElement) -> usize {
752 self * rhs.into()
753 }
754}
755
756impl Mul<usize> for MessageElement {
757 type Output = usize;
758
759 #[inline]
760 fn mul(self, rhs: usize) -> usize {
761 self.into() * rhs
762 }
763}
764
765impl MessageElement {
766 #[inline]
771 fn into(self) -> usize {
772 match self {
773 MessageElement::Static(a, _, _) => a,
774 _ => 0,
775 }
776 }
777}
778
779#[inline]
789pub fn get_needed_message_size(ty: DataType) -> usize {
790 let element = get_message_meta(ty).element;
791 data_type_size(element.data_type()) * element
792}
793
794#[inline]
800pub fn get_info_type(ty: DataType) -> MessageClass {
801 get_message_meta(ty).element.message_type()
802}
803
804#[inline]
811pub fn get_data_type(ty: DataType) -> MessageDataType {
812 get_message_meta(ty).element.data_type()
813}
814
815#[inline]
821#[cfg(feature = "std")]
822pub fn get_message_name(ty: DataType) -> Arc<str> {
823 get_message_meta(ty).name
824}
825
826#[cfg(not(feature = "std"))]
827pub fn get_message_name(ty: DataType) -> &'static str {
828 get_message_meta(ty).name
829}
830
831#[inline]
837#[cfg(feature = "std")]
838pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
839 get_message_meta(ty).endpoints
840}
841
842#[cfg(not(feature = "std"))]
843pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
844 get_message_meta(ty).endpoints
845}
846
847#[allow(dead_code)]
852#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
853pub enum MessageDataType {
854 Float64,
855 Float32,
856 UInt8,
857 UInt16,
858 UInt32,
859 UInt64,
860 UInt128,
861 Int8,
862 Int16,
863 Int32,
864 Int64,
865 Int128,
866 Bool,
867 String,
868 Binary,
869 NoData,
870}
871
872#[inline]
881pub fn data_type_size(dt: MessageDataType) -> usize {
882 match dt {
883 MessageDataType::Float64 => size_of::<f64>(),
884 MessageDataType::Float32 => size_of::<f32>(),
885 MessageDataType::UInt8 => size_of::<u8>(),
886 MessageDataType::UInt16 => size_of::<u16>(),
887 MessageDataType::UInt32 => size_of::<u32>(),
888 MessageDataType::UInt64 => size_of::<u64>(),
889 MessageDataType::UInt128 => size_of::<u128>(),
890 MessageDataType::Int8 => size_of::<i8>(),
891 MessageDataType::Int16 => size_of::<i16>(),
892 MessageDataType::Int32 => size_of::<i32>(),
893 MessageDataType::Int64 => size_of::<i64>(),
894 MessageDataType::Int128 => size_of::<i128>(),
895 MessageDataType::Bool => size_of::<bool>(),
896 MessageDataType::String => runtime_static_string_length(),
897 MessageDataType::Binary => runtime_static_hex_length(),
898 MessageDataType::NoData => 0,
899 }
900}
901
902#[allow(dead_code)]
904#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
905pub enum MessageClass {
906 Data,
908 Error,
910 Warning,
912}
913
914#[derive(Debug, Clone, PartialEq, Eq)]
923pub enum TelemetryError {
924 GenericError(Option<Arc<str>>),
926
927 InvalidType,
929
930 SizeMismatch { expected: usize, got: usize },
932
933 SizeMismatchError,
935
936 EmptyEndpoints,
938
939 TimestampInvalid,
941
942 MissingPayload,
944
945 HandlerError(&'static str),
947
948 BadArg,
950
951 PermissionDenied,
953
954 Pack(&'static str),
956
957 Unpack(&'static str),
959
960 Io(&'static str),
962
963 InvalidUtf8,
965
966 TypeMismatch { expected: usize, got: usize },
968
969 InvalidLinkId(&'static str),
971
972 PacketTooLarge(&'static str),
974}
975
976impl TelemetryError {
977 pub const fn to_error_code(&self) -> TelemetryErrorCode {
980 match self {
981 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
982 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
983 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
984 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
985 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
986 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
987 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
988 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
989 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
990 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
991 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
992 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
993 TelemetryError::Io(_) => TelemetryErrorCode::Io,
994 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
995 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
996 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
997 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
998 }
999 }
1000}
1001
1002impl core::fmt::Display for TelemetryError {
1004 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1005 core::fmt::Debug::fmt(self, f)
1010 }
1011}
1012
1013#[cfg(feature = "std")]
1015impl std::error::Error for TelemetryError {
1016 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1017 None
1018 }
1019}
1020
1021#[cfg(feature = "std")]
1023impl From<Error> for TelemetryError {
1024 fn from(error: Error) -> Self {
1025 let str = error.to_string();
1026 let astr: Arc<str> = Arc::from(str.as_str());
1027 TelemetryError::GenericError(Some(astr))
1028 }
1029}
1030
1031#[cfg(feature = "std")]
1033impl From<Box<dyn std::error::Error>> for TelemetryError {
1034 fn from(err: Box<dyn std::error::Error>) -> Self {
1035 let str = err.to_string();
1036 let astr: Arc<str> = Arc::from(str.as_str());
1037 TelemetryError::GenericError(Some(astr))
1038 }
1039}
1040
1041#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1046#[repr(i32)]
1047pub enum TelemetryErrorCode {
1048 GenericError = -2,
1049 InvalidType = -3,
1050 SizeMismatch = -4,
1051 SizeMismatchError = -5,
1052 EmptyEndpoints = -6,
1053 TimestampInvalid = -7,
1054 MissingPayload = -8,
1055 HandlerError = -9,
1056 BadArg = -10,
1057 PermissionDenied = -11,
1058 Pack = -12,
1059 Unpack = -13,
1060 Io = -14,
1061 InvalidUtf8 = -15,
1062 TypeMismatch = -16,
1063 InvalidLinkId = -17,
1064 PacketTooLarge = -18,
1065}
1066
1067impl_repr_i32_enum!(
1069 TelemetryErrorCode,
1070 TelemetryErrorCode::MAX,
1071 TelemetryErrorCode::MIN
1072);
1073
1074impl TelemetryErrorCode {
1075 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1077
1078 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1080
1081 #[inline]
1085 pub fn as_str(&self) -> &'static str {
1086 match self {
1087 TelemetryErrorCode::GenericError => "GenericError",
1088 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1089 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1090 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1091 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1092 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1093 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1094 TelemetryErrorCode::HandlerError => "{Handler Error}",
1095 TelemetryErrorCode::BadArg => "{Bad Arg}",
1096 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1097 TelemetryErrorCode::Pack => "{Pack Error}",
1098 TelemetryErrorCode::Unpack => "{Unpack Error}",
1099 TelemetryErrorCode::Io => "{IO Error}",
1100 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1101 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1102 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1103 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1104 }
1105 }
1106
1107 #[inline]
1115 pub fn try_from_i32(x: i32) -> Option<Self> {
1116 try_enum_from_i32(x)
1117 }
1118}
1119
1120pub type TelemetryResult<T> = Result<T, TelemetryError>;
1122
1123#[inline]
1135pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1136 if x > E::MAX {
1137 return None;
1138 }
1139 E::from_u32(x)
1140}
1141
1142#[inline]
1150pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1151 if x < E::MIN || x > E::MAX {
1152 return None;
1153 }
1154
1155 let e = unsafe { (&x as *const i32 as *const E).read() };
1157 Some(e)
1158}