1use crate::error::{InvalidId, ParseIdError};
2
3pub const MAX_STANDARD_ID: u16 = 0x7FF;
5
6pub const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF;
8
9#[macro_export]
38macro_rules! can_id {
39 ($n:expr) => {
40 {
41 const N: u32 = ($n);
42 const { ::core::assert!(N <= $crate::MAX_EXTENDED_ID, "invalid CAN ID") };
43 unsafe {
44 if N <= $crate::MAX_STANDARD_ID as u32 {
45 $crate::CanId::Standard($crate::StandardId::new_unchecked(N as u16))
46 } else {
47 $crate::CanId::Extended($crate::ExtendedId::new_unchecked(N))
48 }
49 }
50 }
51 };
52 (standard: $n:expr) => {
53 $crate::CanId::Standard($crate::standard_id!($n))
54 };
55 (extended: $n:expr) => {
56 $crate::CanId::Extended($crate::extended_id!($n))
57 };
58}
59
60#[macro_export]
78macro_rules! standard_id {
79 ($n:expr) => {
80 {
81 #[allow(clippy::all)]
82 const { ::core::assert!(($n) <= $crate::MAX_STANDARD_ID, "invalid standard CAN ID") };
83 unsafe {
84 $crate::StandardId::new_unchecked($n)
85 }
86 }
87 };
88}
89
90#[macro_export]
108macro_rules! extended_id {
109 ($n:expr) => {
110 unsafe {
111 #[allow(clippy::all)]
112 const { ::core::assert!(($n) <= $crate::MAX_EXTENDED_ID, "invalid extended CAN ID"); };
113 $crate::ExtendedId::new_unchecked($n)
114 }
115 };
116}
117
118#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
120#[repr(C)]
121pub enum CanId {
122 Standard(StandardId),
124
125 Extended(ExtendedId),
127}
128
129#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
131#[repr(transparent)]
132pub struct StandardId {
133 id: u16,
135}
136
137#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
139#[repr(transparent)]
140pub struct ExtendedId {
141 id: u32,
143}
144
145impl CanId {
146 pub const fn new(id: u32) -> Result<Self, InvalidId> {
157 if id <= MAX_STANDARD_ID as u32 {
158 let id = id as u16;
159 Ok(Self::Standard(StandardId { id }))
160 } else {
161 match ExtendedId::new(id) {
162 Ok(x) => Ok(Self::Extended(x)),
163 Err(e) => Err(e)
164 }
165 }
166 }
167
168 pub const fn new_standard(id: u16) -> Result<Self, InvalidId> {
173 match StandardId::new(id) {
174 Ok(x) => Ok(Self::Standard(x)),
175 Err(e) => Err(e),
176 }
177 }
178
179 pub const fn new_extended(id: u32) -> Result<Self, InvalidId> {
184 match ExtendedId::new(id) {
185 Ok(x) => Ok(Self::Extended(x)),
186 Err(e) => Err(e),
187 }
188 }
189
190 pub const fn as_u32(self) -> u32 {
192 self.to_extended().as_u32()
193 }
194
195 pub const fn as_standard(self) -> Option<StandardId> {
202 match self {
203 Self::Standard(id) => Some(id),
204 Self::Extended(_) => None,
205 }
206 }
207
208 pub const fn as_extended(self) -> Option<ExtendedId> {
212 match self {
213 Self::Standard(_) => None,
214 Self::Extended(id) => Some(id),
215 }
216 }
217
218 pub const fn to_standard(self) -> Result<StandardId, InvalidId> {
222 match self {
223 Self::Standard(id) => Ok(id),
224 Self::Extended(id) => {
225 if id.as_u32() <= u16::MAX as u32 {
226 StandardId::new(id.as_u32() as u16)
227 } else {
228 Err(InvalidId {
229 id: Some(id.as_u32()),
230 extended: false,
231 })
232 }
233 }
234 }
235 }
236
237 pub const fn to_extended(self) -> ExtendedId {
239 match self {
240 Self::Standard(id) => ExtendedId::from_u16(id.as_u16()),
241 Self::Extended(id) => id,
242 }
243 }
244}
245
246impl StandardId {
247 pub const MAX: Self = Self { id: MAX_STANDARD_ID };
249
250 pub const fn new(id: u16) -> Result<Self, InvalidId> {
254 if id <= MAX_STANDARD_ID {
255 Ok(Self { id })
256 } else {
257 Err(InvalidId {
258 id: Some(id as u32),
259 extended: false,
260 })
261 }
262 }
263
264 pub const fn from_u8(id: u8) -> Self {
269 Self { id: id as u16 }
270 }
271
272 pub const fn as_u16(self) -> u16 {
277 self.id
278 }
279
280 pub const unsafe fn new_unchecked(id: u16) -> Self {
285 debug_assert!(id <= MAX_STANDARD_ID);
286 Self {
287 id
288 }
289 }
290}
291
292impl ExtendedId {
293 pub const MAX: Self = Self { id: MAX_EXTENDED_ID };
295
296 pub const fn new(id: u32) -> Result<Self, InvalidId> {
300 if id <= MAX_EXTENDED_ID {
301 Ok(Self { id })
302 } else {
303 Err(InvalidId {
304 id: Some(id),
305 extended: false,
306 })
307 }
308 }
309
310 pub const fn from_u8(id: u8) -> Self {
315 Self { id: id as u32 }
316 }
317
318 pub const fn from_u16(id: u16) -> Self {
323 Self { id: id as u32 }
324 }
325
326 pub const fn as_u32(self) -> u32 {
331 self.id
332 }
333
334 pub const unsafe fn new_unchecked(id: u32) -> Self {
339 debug_assert!(id <= MAX_EXTENDED_ID);
340 Self {
341 id
342 }
343 }
344}
345
346impl PartialEq<StandardId> for CanId {
347 fn eq(&self, other: &StandardId) -> bool {
348 self.as_standard().is_some_and(|x| x == *other)
349 }
350}
351
352impl PartialEq<CanId> for StandardId {
353 fn eq(&self, other: &CanId) -> bool {
354 other == self
355 }
356}
357
358impl PartialEq<ExtendedId> for CanId {
359 fn eq(&self, other: &ExtendedId) -> bool {
360 self.as_extended().is_some_and(|x| x == *other)
361 }
362}
363
364impl PartialEq<CanId> for ExtendedId {
365 fn eq(&self, other: &CanId) -> bool {
366 other == self
367 }
368}
369
370impl From<u8> for StandardId {
371 fn from(value: u8) -> Self {
372 Self { id: value.into() }
373 }
374}
375
376impl TryFrom<u16> for StandardId {
377 type Error = InvalidId;
378
379 fn try_from(value: u16) -> Result<Self, Self::Error> {
380 Self::new(value)
381 }
382}
383
384impl TryFrom<u32> for StandardId {
385 type Error = InvalidId;
386
387 fn try_from(value: u32) -> Result<Self, Self::Error> {
388 if value > MAX_STANDARD_ID.into() {
389 Err(InvalidId {
390 id: Some(value),
391 extended: false,
392 })
393 } else {
394 Ok(Self { id: value as u16 })
395 }
396 }
397}
398
399impl TryFrom<ExtendedId> for StandardId {
400 type Error = InvalidId;
401
402 fn try_from(value: ExtendedId) -> Result<Self, Self::Error> {
403 Self::try_from(value.as_u32())
404 }
405}
406
407impl TryFrom<CanId> for StandardId {
408 type Error = InvalidId;
409
410 fn try_from(value: CanId) -> Result<Self, Self::Error> {
411 Self::try_from(value.as_u32())
412 }
413}
414
415impl From<u8> for ExtendedId {
416 fn from(value: u8) -> Self {
417 Self { id: value.into() }
418 }
419}
420
421impl From<u16> for ExtendedId {
422 fn from(value: u16) -> Self {
423 Self { id: value.into() }
424 }
425}
426
427impl TryFrom<u32> for ExtendedId {
428 type Error = InvalidId;
429
430 fn try_from(value: u32) -> Result<Self, Self::Error> {
431 Self::new(value)
432 }
433}
434
435impl From<StandardId> for ExtendedId {
436 fn from(value: StandardId) -> Self {
437 value.as_u16().into()
438 }
439}
440
441impl From<CanId> for ExtendedId {
442 fn from(value: CanId) -> Self {
443 value.to_extended()
444 }
445}
446
447impl From<u8> for CanId {
448 fn from(value: u8) -> Self {
449 Self::Standard(value.into())
450 }
451}
452
453impl From<u16> for CanId {
454 fn from(value: u16) -> Self {
455 if value <= MAX_STANDARD_ID {
456 StandardId { id: value }.into()
457 } else {
458 ExtendedId::from(value).into()
459 }
460 }
461}
462
463impl TryFrom<u32> for CanId {
464 type Error = InvalidId;
465
466 fn try_from(value: u32) -> Result<Self, Self::Error> {
467 Self::new(value)
468 }
469}
470
471impl From<StandardId> for CanId {
472 fn from(value: StandardId) -> Self {
473 Self::Standard(value)
474 }
475}
476
477impl From<ExtendedId> for CanId {
478 fn from(value: ExtendedId) -> Self {
479 Self::Extended(value)
480 }
481}
482
483impl std::str::FromStr for StandardId {
484 type Err = ParseIdError;
485
486 fn from_str(input: &str) -> Result<Self, Self::Err> {
487 let id = parse_number(input)
488 .map_err(|e| ParseIdError::invalid_format(e, true))?;
489 let id: u16 = id.try_into()
490 .map_err(|_| ParseIdError::invalid_value(InvalidId { id: Some(id), extended: false }))?;
491 let id = id.try_into()
492 .map_err(|_| ParseIdError::invalid_value(InvalidId { id: Some(id.into()), extended: false }))?;
493 Ok(id)
494 }
495}
496
497impl std::str::FromStr for ExtendedId {
498 type Err = ParseIdError;
499
500 fn from_str(input: &str) -> Result<Self, Self::Err> {
501 let id = parse_number(input)
502 .map_err(|e| ParseIdError::invalid_format(e, true))?;
503 let id = id.try_into()
504 .map_err(|_| ParseIdError::invalid_value(InvalidId { id: Some(id), extended: true }))?;
505 Ok(id)
506 }
507}
508
509impl std::str::FromStr for CanId {
510 type Err = ParseIdError;
511
512 fn from_str(input: &str) -> Result<Self, Self::Err> {
513 let id = parse_number(input)
514 .map_err(|e| ParseIdError::invalid_format(e, true))?;
515 let id = id.try_into()
516 .map_err(|_| ParseIdError::invalid_value(InvalidId { id: Some(id), extended: true }))?;
517 Ok(id)
518 }
519}
520
521fn parse_number(input: &str) -> Result<u32, std::num::ParseIntError> {
522 if let Some(hexadecimal) = input.strip_prefix("0x") {
523 u32::from_str_radix(hexadecimal, 16)
524 } else if let Some(octal) = input.strip_prefix("0o") {
525 u32::from_str_radix(octal, 8)
526 } else if let Some(binary) = input.strip_prefix("0b") {
527 u32::from_str_radix(binary, 2)
528 } else {
529 input.parse()
530 }
531}
532
533impl std::fmt::Debug for CanId {
534 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
535 match self {
536 Self::Standard(id) => id.fmt(f),
537 Self::Extended(id) => id.fmt(f),
538 }
539 }
540}
541
542impl std::fmt::Debug for StandardId {
543 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
544 f.debug_tuple("StandardId")
545 .field(&format_args!("0x{:03X}", self.id))
546 .finish()
547 }
548}
549
550impl std::fmt::Debug for ExtendedId {
551 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552 f.debug_tuple("ExtendedId")
553 .field(&format_args!("0x{:08X}", self.id))
554 .finish()
555 }
556}
557
558impl std::fmt::LowerHex for StandardId {
559 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
560 self.as_u16().fmt(f)
561 }
562}
563
564impl std::fmt::LowerHex for ExtendedId {
565 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
566 self.as_u32().fmt(f)
567 }
568}
569
570impl std::fmt::LowerHex for CanId {
571 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
572 match self {
573 Self::Standard(x) => x.fmt(f),
574 Self::Extended(x) => x.fmt(f),
575 }
576 }
577}
578
579impl std::fmt::UpperHex for StandardId {
580 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
581 self.as_u16().fmt(f)
582 }
583}
584
585impl std::fmt::UpperHex for ExtendedId {
586 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
587 self.as_u32().fmt(f)
588 }
589}
590
591impl std::fmt::UpperHex for CanId {
592 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
593 match self {
594 Self::Standard(x) => x.fmt(f),
595 Self::Extended(x) => x.fmt(f),
596 }
597 }
598}