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