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 type_stats;
193mod varint;
194pub mod wire_format;
195pub const MAX_VALUE_DATA_ENDPOINT: u32 = 255;
201
202pub const MAX_VALUE_DATA_TYPE: u32 = 4095;
204
205pub const MAX_VALUE_ROUTE_SELECTION_MODE: i32 = 2;
207
208impl ReprU32Enum for DataType {
209 const MAX: u32 = u32::MAX;
210
211 #[inline]
212 fn from_u32(x: u32) -> Option<Self> {
213 DataType::try_from_u32(x)
214 }
215}
216
217impl ReprU32Enum for DataEndpoint {
218 const MAX: u32 = u32::MAX;
219
220 #[inline]
221 fn from_u32(x: u32) -> Option<Self> {
222 DataEndpoint::try_from_u32(x)
223 }
224}
225
226#[inline]
227pub fn current_max_endpoint_id() -> u32 {
228 max_endpoint_id()
229}
230
231#[inline]
232pub fn current_max_data_type_id() -> u32 {
233 max_data_type_id()
234}
235
236#[repr(i32)]
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
238pub enum RouteSelectionMode {
239 Fanout = 0,
240 Weighted = 1,
241 Failover = 2,
242}
243
244impl_repr_i32_enum!(
245 RouteSelectionMode,
246 RouteSelectionMode::Fanout as i32,
247 RouteSelectionMode::Failover as i32
248);
249
250#[inline]
251const fn parse_usize(s: &str) -> usize {
252 let bytes = s.as_bytes();
253 let mut i = 0;
254 let mut val = 0;
255
256 while i < bytes.len() {
257 let c = bytes[i];
258 if c < b'0' || c > b'9' {
259 panic!("Invalid digit");
260 }
261 val = val * 10 + (c - b'0') as usize;
262 i += 1;
263 }
264 val
265}
266
267#[inline]
268pub const fn parse_f64(s: &str) -> f64 {
269 let bytes = s.as_bytes();
270 let mut i = 0;
271
272 if bytes.is_empty() {
273 panic!("empty string");
274 }
275
276 let mut sign = 1.0;
278 if bytes[i] == b'-' {
279 sign = -1.0;
280 i += 1;
281 } else if bytes[i] == b'+' {
282 i += 1;
283 }
284
285 let mut int_part: f64 = 0.0;
286 let mut has_digits = false;
287
288 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
289 int_part = int_part * 10.0 + (bytes[i] - b'0') as f64;
290 i += 1;
291 has_digits = true;
292 }
293
294 let mut frac_part: f64 = 0.0;
295 let mut scale: f64 = 1.0;
296
297 if i < bytes.len() && bytes[i] == b'.' {
298 i += 1;
299
300 while i < bytes.len() && bytes[i] >= b'0' && bytes[i] <= b'9' {
301 scale *= 10.0;
302 frac_part += (bytes[i] - b'0') as f64 / scale;
303 i += 1;
304 has_digits = true;
305 }
306 }
307
308 if !has_digits || i != bytes.len() {
309 panic!("invalid f64 literal");
310 }
311
312 sign * (int_part + frac_part)
313}
314
315#[inline(always)]
316const fn parse_strings(s: &str) -> &str {
317 s
318}
319
320#[inline]
321pub const fn parse_u8(s: &str) -> u8 {
322 let bytes = s.as_bytes();
323 let mut i = 0;
324 let mut val: u16 = 0;
325
326 if bytes.is_empty() {
327 panic!("empty string");
328 }
329
330 while i < bytes.len() {
331 let c = bytes[i];
332 if c < b'0' || c > b'9' {
333 panic!("invalid digit in u8");
334 }
335
336 val = val * 10 + (c - b'0') as u16;
337 if val > 255 {
338 panic!("u8 overflow");
339 }
340
341 i += 1;
342 }
343
344 val as u8
345}
346
347#[inline]
348pub const fn parse_u128(s: &str) -> u128 {
349 let bytes = s.as_bytes();
350 let mut i = 0;
351 let mut val: u128 = 0;
352
353 if bytes.is_empty() {
354 panic!("empty string");
355 }
356
357 while i < bytes.len() {
358 let c = bytes[i];
359 if c < b'0' || c > b'9' {
360 panic!("invalid digit in u128");
361 }
362
363 let digit = (c - b'0') as u128;
364
365 if val > (u128::MAX - digit) / 10 {
368 panic!("u128 overflow");
369 }
370
371 val = val * 10 + digit;
372 i += 1;
373 }
374
375 val
376}
377
378#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
382pub struct EndpointMeta {
383 #[cfg(feature = "std")]
385 name: Arc<str>,
386 #[cfg(not(feature = "std"))]
387 name: &'static str,
388 #[cfg(feature = "std")]
390 description: Arc<str>,
391 #[cfg(not(feature = "std"))]
392 description: &'static str,
393 link_local_only: bool,
395}
396
397impl EndpointMeta {
398 #[cfg(feature = "std")]
399 pub(crate) fn name_ref(&self) -> &str {
400 self.name.as_ref()
401 }
402
403 #[cfg(not(feature = "std"))]
404 pub(crate) fn name_ref(&self) -> &str {
405 self.name
406 }
407
408 #[cfg(feature = "std")]
409 pub(crate) fn description_ref(&self) -> &str {
410 self.description.as_ref()
411 }
412
413 #[cfg(not(feature = "std"))]
414 pub(crate) fn description_ref(&self) -> &str {
415 self.description
416 }
417
418 #[cfg(feature = "std")]
424 pub fn as_str(&self) -> Arc<str> {
425 self.name.clone()
426 }
427
428 #[cfg(not(feature = "std"))]
429 pub fn as_str(&self) -> &'static str {
430 self.name
431 }
432
433 #[inline]
435 #[cfg(feature = "std")]
436 pub fn description(&self) -> Arc<str> {
437 self.description.clone()
438 }
439
440 #[cfg(not(feature = "std"))]
441 pub fn description(&self) -> &'static str {
442 self.description
443 }
444
445 #[inline]
447 pub fn is_link_local_only(&self) -> bool {
448 self.link_local_only
449 }
450}
451
452impl DataEndpoint {
453 #[cfg(feature = "std")]
459 pub fn as_str(&self) -> Arc<str> {
460 get_endpoint_meta(*self).name
461 }
462
463 #[cfg(not(feature = "std"))]
464 pub fn as_str(&self) -> &'static str {
465 get_endpoint_meta(*self).name
466 }
467
468 #[cfg(feature = "std")]
470 pub fn description(&self) -> Arc<str> {
471 get_endpoint_meta(*self).description
472 }
473
474 #[cfg(not(feature = "std"))]
475 pub fn description(&self) -> &'static str {
476 get_endpoint_meta(*self).description
477 }
478
479 #[inline]
481 pub fn is_link_local_only(&self) -> bool {
482 get_endpoint_meta(*self).link_local_only
483 }
484}
485
486#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
488pub enum MessageElement {
489 Static(usize, MessageDataType, MessageClass),
493 Dynamic(MessageDataType, MessageClass),
497}
498
499impl MessageElement {
500 #[inline]
502 pub const fn data_type(&self) -> MessageDataType {
503 match self {
504 MessageElement::Static(_, dt, _) => *dt,
505 MessageElement::Dynamic(dt, _) => *dt,
506 }
507 }
508
509 #[inline]
511 pub const fn message_type(&self) -> MessageClass {
512 match self {
513 MessageElement::Static(_, _, mt) => *mt,
514 MessageElement::Dynamic(_, mt) => *mt,
515 }
516 }
517}
518
519#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
521#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
522pub enum ReliableMode {
523 #[cfg_attr(feature = "serde", serde(rename = "Off"))]
525 None,
526 Ordered,
528 Unordered,
530}
531
532#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
534pub enum E2eEncryptionPolicy {
535 PreferOff,
537 PreferOn,
539 RequireOn,
541}
542
543#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
545pub struct MessageMeta {
546 #[cfg(feature = "std")]
547 name: Arc<str>,
548 #[cfg(not(feature = "std"))]
549 name: &'static str,
550 #[cfg(feature = "std")]
552 description: Arc<str>,
553 #[cfg(not(feature = "std"))]
554 description: &'static str,
555 element: MessageElement,
557 #[cfg(feature = "std")]
559 endpoints: Arc<[DataEndpoint]>,
560 #[cfg(not(feature = "std"))]
561 endpoints: &'static [DataEndpoint],
562 reliable: ReliableMode,
564 priority: u8,
566 e2e_encryption: E2eEncryptionPolicy,
568}
569
570impl MessageMeta {
571 pub(crate) fn endpoints_owned(&self) -> Arc<[DataEndpoint]> {
572 #[cfg(feature = "std")]
573 {
574 self.endpoints.clone()
575 }
576 #[cfg(not(feature = "std"))]
577 {
578 Arc::from(self.endpoints)
579 }
580 }
581
582 #[cfg(feature = "std")]
583 pub(crate) fn name_ref(&self) -> &str {
584 self.name.as_ref()
585 }
586
587 #[cfg(not(feature = "std"))]
588 pub(crate) fn name_ref(&self) -> &str {
589 self.name
590 }
591
592 #[cfg(feature = "std")]
593 pub(crate) fn description_ref(&self) -> &str {
594 self.description.as_ref()
595 }
596
597 #[cfg(not(feature = "std"))]
598 pub(crate) fn description_ref(&self) -> &str {
599 self.description
600 }
601
602 #[cfg(feature = "std")]
603 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
604 self.endpoints.as_ref()
605 }
606
607 #[cfg(not(feature = "std"))]
608 pub(crate) fn endpoints_ref(&self) -> &[DataEndpoint] {
609 self.endpoints
610 }
611}
612
613impl DataType {
614 #[cfg(feature = "std")]
616 pub fn as_str(&self) -> Arc<str> {
617 get_message_meta(*self).name
618 }
619
620 #[cfg(not(feature = "std"))]
621 pub fn as_str(&self) -> &'static str {
622 get_message_meta(*self).name
623 }
624
625 #[cfg(feature = "std")]
627 pub fn description(&self) -> Arc<str> {
628 get_message_meta(*self).description
629 }
630
631 #[cfg(not(feature = "std"))]
632 pub fn description(&self) -> &'static str {
633 get_message_meta(*self).description
634 }
635}
636#[inline]
642pub fn message_meta(ty: DataType) -> MessageMeta {
643 get_message_meta(ty)
644}
645
646#[inline]
648pub fn is_reliable_type(ty: DataType) -> bool {
649 !matches!(reliable_mode(ty), ReliableMode::None)
650}
651
652#[inline]
654pub fn reliable_mode(ty: DataType) -> ReliableMode {
655 config::message_delivery_meta(ty).0
656}
657
658#[inline]
660pub fn message_priority(ty: DataType) -> u8 {
661 config::message_delivery_meta(ty).1
662}
663
664#[inline]
672pub fn transport_priority(ty: DataType) -> u8 {
673 match ty {
674 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest => {
677 255
678 }
679
680 DataType::DiscoveryAnnounce
682 | DataType::DiscoveryTimeSyncSources
683 | DataType::DiscoveryTopology
684 | DataType::DiscoveryTopologyRequest
685 | DataType::DiscoveryLeave
686 | DataType::DiscoveryLinkCapabilities
687 | DataType::DiscoveryAddress => 255,
688
689 DataType::DiscoverySchema
694 | DataType::DiscoverySchemaRequest
695 | DataType::ManagedVariableRequest
696 | DataType::ManagedVariableValue
697 | DataType::TimeSyncAnnounce
698 | DataType::TimeSyncRequest
699 | DataType::TimeSyncResponse => 254,
700
701 _ => message_priority(ty).min(253),
703 }
704}
705
706#[inline]
709pub(crate) fn small_frozen_control(
710 ty: DataType,
711 owners: usize,
712 shape: Option<MessageElement>,
713) -> bool {
714 if !(1..=3).contains(&owners) {
715 return false;
716 }
717 config::try_get_message_meta(ty).is_some_and(|meta| {
718 matches!(
719 meta.element,
720 MessageElement::Static(0..=16, MessageDataType::UInt8, _)
721 ) && matches!(
722 shape,
723 None | Some(MessageElement::Static(0..=16, MessageDataType::UInt8, _))
724 )
725 })
726}
727
728#[inline]
730pub(crate) fn scheduler_priority(ty: DataType) -> u8 {
731 transport_priority(ty)
732}
733
734#[inline]
736pub fn message_e2e_encryption_policy(ty: DataType) -> E2eEncryptionPolicy {
737 get_message_meta(ty).e2e_encryption
738}
739
740impl Mul<MessageElement> for usize {
743 type Output = usize;
744
745 #[inline]
746 fn mul(self, rhs: MessageElement) -> usize {
747 self * rhs.into()
748 }
749}
750
751impl Mul<usize> for MessageElement {
752 type Output = usize;
753
754 #[inline]
755 fn mul(self, rhs: usize) -> usize {
756 self.into() * rhs
757 }
758}
759
760impl MessageElement {
761 #[inline]
766 fn into(self) -> usize {
767 match self {
768 MessageElement::Static(a, _, _) => a,
769 _ => 0,
770 }
771 }
772}
773
774#[inline]
784pub fn get_needed_message_size(ty: DataType) -> usize {
785 let element = get_message_meta(ty).element;
786 data_type_size(element.data_type()) * element
787}
788
789#[inline]
795pub fn get_info_type(ty: DataType) -> MessageClass {
796 get_message_meta(ty).element.message_type()
797}
798
799#[inline]
806pub fn get_data_type(ty: DataType) -> MessageDataType {
807 get_message_meta(ty).element.data_type()
808}
809
810#[inline]
816#[cfg(feature = "std")]
817pub fn get_message_name(ty: DataType) -> Arc<str> {
818 get_message_meta(ty).name
819}
820
821#[cfg(not(feature = "std"))]
822pub fn get_message_name(ty: DataType) -> &'static str {
823 get_message_meta(ty).name
824}
825
826#[inline]
832#[cfg(feature = "std")]
833pub fn endpoints_from_datatype(ty: DataType) -> Arc<[DataEndpoint]> {
834 get_message_meta(ty).endpoints
835}
836
837#[cfg(not(feature = "std"))]
838pub fn endpoints_from_datatype(ty: DataType) -> &'static [DataEndpoint] {
839 get_message_meta(ty).endpoints
840}
841
842#[allow(dead_code)]
847#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
848pub enum MessageDataType {
849 Float64,
850 Float32,
851 UInt8,
852 UInt16,
853 UInt32,
854 UInt64,
855 UInt128,
856 Int8,
857 Int16,
858 Int32,
859 Int64,
860 Int128,
861 Bool,
862 String,
863 Binary,
864 NoData,
865}
866
867#[inline]
876pub fn data_type_size(dt: MessageDataType) -> usize {
877 match dt {
878 MessageDataType::Float64 => size_of::<f64>(),
879 MessageDataType::Float32 => size_of::<f32>(),
880 MessageDataType::UInt8 => size_of::<u8>(),
881 MessageDataType::UInt16 => size_of::<u16>(),
882 MessageDataType::UInt32 => size_of::<u32>(),
883 MessageDataType::UInt64 => size_of::<u64>(),
884 MessageDataType::UInt128 => size_of::<u128>(),
885 MessageDataType::Int8 => size_of::<i8>(),
886 MessageDataType::Int16 => size_of::<i16>(),
887 MessageDataType::Int32 => size_of::<i32>(),
888 MessageDataType::Int64 => size_of::<i64>(),
889 MessageDataType::Int128 => size_of::<i128>(),
890 MessageDataType::Bool => size_of::<bool>(),
891 MessageDataType::String => runtime_static_string_length(),
892 MessageDataType::Binary => runtime_static_hex_length(),
893 MessageDataType::NoData => 0,
894 }
895}
896
897#[allow(dead_code)]
899#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
900pub enum MessageClass {
901 Data,
903 Error,
905 Warning,
907}
908
909#[derive(Debug, Clone, PartialEq, Eq)]
918pub enum TelemetryError {
919 GenericError(Option<Arc<str>>),
921
922 InvalidType,
924
925 SizeMismatch { expected: usize, got: usize },
927
928 SizeMismatchError,
930
931 EmptyEndpoints,
933
934 TimestampInvalid,
936
937 MissingPayload,
939
940 HandlerError(&'static str),
942
943 BadArg,
945
946 PermissionDenied,
948
949 Pack(&'static str),
951
952 Unpack(&'static str),
954
955 Io(&'static str),
957
958 InvalidUtf8,
960
961 TypeMismatch { expected: usize, got: usize },
963
964 InvalidLinkId(&'static str),
966
967 PacketTooLarge(&'static str),
969}
970
971impl TelemetryError {
972 pub const fn to_error_code(&self) -> TelemetryErrorCode {
975 match self {
976 TelemetryError::GenericError(_) => TelemetryErrorCode::GenericError,
977 TelemetryError::InvalidType => TelemetryErrorCode::InvalidType,
978 TelemetryError::SizeMismatch { .. } => TelemetryErrorCode::SizeMismatch,
979 TelemetryError::SizeMismatchError => TelemetryErrorCode::SizeMismatchError,
980 TelemetryError::EmptyEndpoints => TelemetryErrorCode::EmptyEndpoints,
981 TelemetryError::TimestampInvalid => TelemetryErrorCode::TimestampInvalid,
982 TelemetryError::MissingPayload => TelemetryErrorCode::MissingPayload,
983 TelemetryError::HandlerError(_) => TelemetryErrorCode::HandlerError,
984 TelemetryError::BadArg => TelemetryErrorCode::BadArg,
985 TelemetryError::PermissionDenied => TelemetryErrorCode::PermissionDenied,
986 TelemetryError::Pack(_) => TelemetryErrorCode::Pack,
987 TelemetryError::Unpack(_) => TelemetryErrorCode::Unpack,
988 TelemetryError::Io(_) => TelemetryErrorCode::Io,
989 TelemetryError::InvalidUtf8 => TelemetryErrorCode::InvalidUtf8,
990 TelemetryError::TypeMismatch { .. } => TelemetryErrorCode::TypeMismatch,
991 TelemetryError::InvalidLinkId(_) => TelemetryErrorCode::InvalidLinkId,
992 TelemetryError::PacketTooLarge(_) => TelemetryErrorCode::PacketTooLarge,
993 }
994 }
995}
996
997impl core::fmt::Display for TelemetryError {
999 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1000 core::fmt::Debug::fmt(self, f)
1005 }
1006}
1007
1008#[cfg(feature = "std")]
1010impl std::error::Error for TelemetryError {
1011 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1012 None
1013 }
1014}
1015
1016#[cfg(feature = "std")]
1018impl From<Error> for TelemetryError {
1019 fn from(error: Error) -> Self {
1020 let str = error.to_string();
1021 let astr: Arc<str> = Arc::from(str.as_str());
1022 TelemetryError::GenericError(Some(astr))
1023 }
1024}
1025
1026#[cfg(feature = "std")]
1028impl From<Box<dyn std::error::Error>> for TelemetryError {
1029 fn from(err: Box<dyn std::error::Error>) -> Self {
1030 let str = err.to_string();
1031 let astr: Arc<str> = Arc::from(str.as_str());
1032 TelemetryError::GenericError(Some(astr))
1033 }
1034}
1035
1036#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1041#[repr(i32)]
1042pub enum TelemetryErrorCode {
1043 GenericError = -2,
1044 InvalidType = -3,
1045 SizeMismatch = -4,
1046 SizeMismatchError = -5,
1047 EmptyEndpoints = -6,
1048 TimestampInvalid = -7,
1049 MissingPayload = -8,
1050 HandlerError = -9,
1051 BadArg = -10,
1052 PermissionDenied = -11,
1053 Pack = -12,
1054 Unpack = -13,
1055 Io = -14,
1056 InvalidUtf8 = -15,
1057 TypeMismatch = -16,
1058 InvalidLinkId = -17,
1059 PacketTooLarge = -18,
1060}
1061
1062impl_repr_i32_enum!(
1064 TelemetryErrorCode,
1065 TelemetryErrorCode::MAX,
1066 TelemetryErrorCode::MIN
1067);
1068
1069impl TelemetryErrorCode {
1070 pub const MAX: i32 = TelemetryErrorCode::InvalidType as i32;
1072
1073 pub const MIN: i32 = TelemetryErrorCode::PacketTooLarge as i32;
1075
1076 #[inline]
1080 pub fn as_str(&self) -> &'static str {
1081 match self {
1082 TelemetryErrorCode::GenericError => "GenericError",
1083 TelemetryErrorCode::InvalidType => "{Invalid Type}",
1084 TelemetryErrorCode::SizeMismatch => "{Size Mismatch}",
1085 TelemetryErrorCode::SizeMismatchError => "{Size Mismatch Error}",
1086 TelemetryErrorCode::EmptyEndpoints => "{Empty Endpoints}",
1087 TelemetryErrorCode::TimestampInvalid => "{Timestamp Invalid}",
1088 TelemetryErrorCode::MissingPayload => "{Missing Payload}",
1089 TelemetryErrorCode::HandlerError => "{Handler Error}",
1090 TelemetryErrorCode::BadArg => "{Bad Arg}",
1091 TelemetryErrorCode::PermissionDenied => "{Permission Denied}",
1092 TelemetryErrorCode::Pack => "{Pack Error}",
1093 TelemetryErrorCode::Unpack => "{Unpack Error}",
1094 TelemetryErrorCode::Io => "{IO Error}",
1095 TelemetryErrorCode::InvalidUtf8 => "{Invalid UTF-8}",
1096 TelemetryErrorCode::TypeMismatch => "{Type Mismatch}",
1097 TelemetryErrorCode::InvalidLinkId => "{Invalid Link ID}",
1098 TelemetryErrorCode::PacketTooLarge => "{Packet Too Large}",
1099 }
1100 }
1101
1102 #[inline]
1110 pub fn try_from_i32(x: i32) -> Option<Self> {
1111 try_enum_from_i32(x)
1112 }
1113}
1114
1115pub type TelemetryResult<T> = Result<T, TelemetryError>;
1117
1118#[inline]
1130pub fn try_enum_from_u32<E: ReprU32Enum>(x: u32) -> Option<E> {
1131 if x > E::MAX {
1132 return None;
1133 }
1134 E::from_u32(x)
1135}
1136
1137#[inline]
1145pub fn try_enum_from_i32<E: ReprI32Enum>(x: i32) -> Option<E> {
1146 if x < E::MIN || x > E::MAX {
1147 return None;
1148 }
1149
1150 let e = unsafe { (&x as *const i32 as *const E).read() };
1152 Some(e)
1153}