1#![doc = include_str!("../README.md")]
2#![no_std]
3
4use core::{
5 fmt::{Debug, Display},
6 marker::PhantomData,
7 ops::{
8 Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, Mul, Rem, Shl,
9 ShlAssign, Shr, ShrAssign, Sub,
10 },
11};
12
13use num_traits::{Bounded, Num, One, Zero};
14#[doc(hidden)]
16#[cfg(feature = "serde")]
17pub use serde;
18
19mod types;
20
21pub use types::{
22 i10, i11, i12, i13, i14, i15, i17, i18, i19, i2, i20, i21, i22, i23, i24, i25, i26, i27, i28,
23 i29, i3, i30, i31, i33, i34, i35, i36, i37, i38, i39, i4, i40, i41, i42, i43, i44, i45, i46,
24 i47, i48, i49, i5, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i6, i60, i61, i62, i63,
25 i7, i9, u1, u10, u11, u12, u13, u14, u15, u17, u18, u19, u2, u20, u21, u22, u23, u24, u25, u26,
26 u27, u28, u29, u3, u30, u31, u33, u34, u35, u36, u37, u38, u39, u4, u40, u41, u42, u43, u44,
27 u45, u46, u47, u48, u49, u5, u50, u51, u52, u53, u54, u55, u56, u57, u58, u59, u6, u60, u61,
28 u62, u63, u7, u9,
29};
30
31#[repr(transparent)]
42#[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
43pub struct UnsafeStorage<T>(T);
44
45impl<T> UnsafeStorage<T> {
46 pub const unsafe fn new_unsafe(inner: T) -> Self {
52 Self(inner)
53 }
54
55 pub unsafe fn as_ref_mut(&mut self) -> &mut T {
61 &mut self.0
62 }
63}
64
65impl<T> AsRef<T> for UnsafeStorage<T> {
66 fn as_ref(&self) -> &T {
68 &self.0
69 }
70}
71
72impl<T: Copy> UnsafeStorage<T> {
73 pub const fn inner(&self) -> T {
75 self.0
76 }
77}
78
79pub unsafe trait BitCount {
90 const COUNT: usize;
92}
93
94pub trait FieldStorage {
96 type StoredType;
98 fn inner_raw(self) -> Self::StoredType;
100}
101
102pub trait BitsFitIn<T> {
111 fn fit(self) -> T;
113}
114
115pub unsafe trait ValidCheck<P> {
129 const ALWAYS_VALID: bool = false;
133 fn is_valid(_input: P) -> bool {
136 true
137 }
138}
139
140pub struct GetSet<'a, P, T, const START: usize, const STOP: usize> {
142 parent: &'a mut P,
144 _phantom: PhantomData<&'a mut T>,
146}
147
148impl<'a, P, T, const START: usize, const STOP: usize> GetSet<'a, P, T, START, STOP> {
149 pub const fn start(&self) -> usize {
151 START
152 }
153
154 pub const fn stop(&self) -> usize {
156 STOP
157 }
158}
159
160impl<
161 'a,
162 P: Num + Bounded + ShlAssign<usize> + ShrAssign<usize> + BitCount,
163 T,
164 const START: usize,
165 const STOP: usize,
166 > GetSet<'a, P, T, START, STOP>
167{
168 pub fn new(parent: &'a mut P) -> Self {
171 Self {
172 parent,
173 _phantom: PhantomData::default(),
174 }
175 }
176
177 #[allow(clippy::unused_self)]
183 fn mask(&self) -> P {
184 let num_bits = P::COUNT;
185 let mut max_value = P::max_value();
186 let keep_bits = STOP - START + 1;
187
188 max_value >>= num_bits - keep_bits;
189 max_value
190 }
191}
192
193impl<
194 'a,
195 P: Num
196 + Shl<usize, Output = P>
197 + Shr<usize, Output = P>
198 + ShlAssign<usize>
199 + ShrAssign<usize>
200 + Bounded
201 + BitAnd<Output = P>
202 + Copy
203 + BitCount,
204 T: ValidCheck<P>,
205 const START: usize,
206 const STOP: usize,
207 > GetSet<'a, P, T, START, STOP>
208{
209 pub fn get(&self) -> T {
211 let section = self.get_raw();
212 unsafe { core::mem::transmute_copy(§ion) }
216 }
217
218 pub fn is_valid(&self) -> bool {
221 let section = self.get_raw();
222 T::is_valid(section)
223 }
224
225 pub fn get_raw(&self) -> P {
228 let parent = *self.parent;
229 let mask = self.mask();
230 (parent >> START) & mask
231 }
232}
233
234impl<'a, P, T, const START: usize, const STOP: usize> GetSet<'a, P, T, START, STOP>
235where
236 T: FieldStorage + BitsFitIn<P>,
237 P: Num
238 + Shl<usize, Output = P>
239 + Copy
240 + BitOrAssign
241 + BitXorAssign
242 + BitAnd<Output = P>
243 + ShlAssign<usize>
244 + ShrAssign<usize>
245 + PartialOrd
246 + Bounded
247 + Sized
248 + BitCount,
249{
250 pub fn set(&mut self, value: T) {
252 unsafe { self.set_raw(value.fit()) }
256 }
257
258 pub unsafe fn set_raw(&mut self, value: P) {
263 let mask = self.mask();
264 let mask_shifted = mask << START;
265
266 *self.parent |= mask_shifted;
268 *self.parent ^= mask_shifted;
269
270 let to_set = value & mask;
271 *self.parent |= to_set << START;
272 }
273}
274
275pub trait BitStruct<const ALWAYS_VALID: bool> {
279 type Kind;
281 unsafe fn from_unchecked(value: Self::Kind) -> Self;
294}
295
296pub trait BitStructExt: BitStruct<true> {
299 fn exact_from(value: Self::Kind) -> Self;
301}
302
303impl<T: BitStruct<true>> BitStructExt for T {
304 fn exact_from(value: Self::Kind) -> Self {
305 unsafe { Self::from_unchecked(value) }
309 }
310}
311
312#[doc(hidden)]
313#[macro_export]
314macro_rules! impl_fields {
315 ($on: expr, $kind: ty =>[$($first_field_meta: meta),*], $head_field: ident, $head_actual: ty $(, [$($field_meta: meta),*], $field: ident, $actual: ty)*) => {
316 $(#[$first_field_meta])*
317 pub fn $head_field(&mut self) -> $crate::GetSet<'_, $kind, $head_actual, {$on - <$head_actual as $crate::BitCount>::COUNT}, {$on - 1}> {
318 $crate::GetSet::new(unsafe {self.0.as_ref_mut()})
319 }
320
321 $crate::impl_fields!($on - <$head_actual as $crate::BitCount>::COUNT, $kind => $([$($field_meta),*], $field, $actual),*);
322 };
323 ($on: expr, $kind: ty =>) => {};
324}
325
326#[doc(hidden)]
328#[macro_export]
329macro_rules! bit_struct_impl {
330 (
331 $(#[$meta: meta])*
332 $struct_vis: vis struct $name: ident ($kind: ty) {
333 $(
334 $(#[$field_meta: meta])*
335 $field: ident: $actual: ty
336 ),* $(,)?
337 }
338 ) => {
339
340 impl $name {
341
342 pub unsafe fn empty() -> Self {
344 unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) }
345 }
346
347 #[doc = concat!("Returns a valid representation for [`", stringify!($name), "`] where all values are")]
348 pub fn of_defaults() -> Self {
353 let mut res = unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) };
354 $(
355 res.$field().set(Default::default());
356 )*
357 res
358 }
359 }
360
361 impl ::core::fmt::Debug for $name {
362 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result {
363 let mut copied = *self;
364 f.debug_struct(stringify!($name))
365 $(
366 .field(stringify!($field), &copied.$field().get())
367 )*
368 .finish()
369 }
370 }
371 };
372}
373
374#[doc(hidden)]
376#[macro_export]
377#[cfg(not(feature = "serde"))]
378macro_rules! bit_struct_serde_impl {
379 (
380 $(#[$meta:meta])*
381 $struct_vis:vis struct
382 $name:ident($kind:ty) { $($(#[$field_meta:meta])* $field:ident : $actual:ty),* $(,)? }
383 ) => {};
384}
385#[doc(hidden)]
387#[macro_export]
388#[cfg(feature = "serde")]
389macro_rules! bit_struct_serde_impl {
390 (
391 $(#[$meta:meta])*
392 $struct_vis: vis struct $name: ident ($kind: ty) {
393 $(
394 $(#[$field_meta:meta])*
395 $field: ident: $actual: ty
396 ),* $(,)?
397 }
398 ) => {
399 #[allow(clippy::used_underscore_binding)]
400 impl $crate::serde::Serialize for $name {
401 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: $crate::serde::Serializer {
402 use $crate::serde::ser::SerializeStruct;
403
404 let mut v = *self;
405
406 let mut serializer = serializer.serialize_struct(
407 stringify!($name),
408 $crate::count_idents!( 0, [$( $field ),*] ),
409 )?;
410 $(
411 serializer.serialize_field(
412 stringify!($field),
413 &v.$field().get()
414 )?;
415 )*
416 serializer.end()
417 }
418 }
419
420 #[allow(clippy::used_underscore_binding)]
421 impl<'de> $crate::serde::Deserialize<'de> for $name {
422 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: $crate::serde::Deserializer<'de> {
423
424 use $crate::serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
425 use ::core::fmt;
426
427 const FIELDS: &'static [&'static str] = &[ $( stringify!( $field ) ),* ];
428
429 #[allow(non_camel_case_types)]
430 enum Fields { $( $field ),* }
431 impl<'de> Deserialize<'de> for Fields {
432 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
433 struct FieldVisitor;
434 impl<'de> Visitor<'de> for FieldVisitor {
435 type Value = Fields;
436
437 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438 f.write_str(stringify!( $( $field ),* ))
439 }
440
441 fn visit_str<E: de::Error>(self, value: &str) -> Result<Fields, E> {
442 match value {
443 $( stringify!( $field ) => Ok(Fields::$field), )*
444 _ => Err(de::Error::unknown_field(value, FIELDS)),
445 }
446 }
447 }
448
449 deserializer.deserialize_identifier(FieldVisitor)
450 }
451 }
452
453 struct BitStructVisitor;
454 impl<'de> Visitor<'de> for BitStructVisitor {
455 type Value = $name;
456
457 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
458 f.write_str(concat!("struct ", stringify!($name)))
459 }
460
461 fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<$name, V::Error> {
462 $( let mut $field: Option<$actual> = None; )*
463 while let Some(key) = map.next_key::<Fields>()? {
464 match key {
465 $( Fields::$field => {
466 if $field.is_some() {
467 return Err(de::Error::duplicate_field(stringify!($field)));
468 }
469 $field = Some(map.next_value()?);
470 },)*
471 }
472 }
473 $(
474 let $field = $field.ok_or_else(|| de::Error::missing_field(stringify!($field)))?;
475 )*
476 Ok($name::new( $( $field ),* ))
477 }
478
479 fn visit_seq<V: SeqAccess<'de>>(self, mut seq: V) -> Result<$name, V::Error> {
480 let mut count = 0;
481 $(
482 let $field = seq.next_element()?
483 .ok_or_else(|| de::Error::invalid_length(count, &self))?;
484 count += 1;
485 )*
486 Ok($name::new( $( $field ),* ))
487 }
488 }
489 deserializer.deserialize_struct(stringify!($name), FIELDS, BitStructVisitor)
490 }
491 }
492 }
493}
494
495pub trait BitStructZero: Zero {
497 fn bs_zero() -> Self {
499 Self::zero()
500 }
501}
502
503impl<T: Zero> BitStructZero for T {}
504
505#[allow(clippy::needless_doctest_main)]
508#[macro_export]
595macro_rules! bit_struct {
596 (
597 $(
598 $(#[$meta:meta])*
599 $struct_vis: vis struct $name: ident ($kind: ty) {
600 $(
601 $(#[$field_meta:meta])*
602 $field: ident: $actual: ty
603 ),* $(,)?
604 }
605 )*
606 ) => {
607 $(
608 $(#[$meta])*
609 #[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
610 pub struct $name($crate::UnsafeStorage<$kind>);
611
612 $crate::bit_struct_serde_impl! {
613 $(#[$meta])*
614 $struct_vis struct $name ($kind) {
615 $(
616 $(#[$field_meta])*
617 $field: $actual
618 ),*
619 }
620 }
621
622 #[allow(clippy::used_underscore_binding)]
623 impl TryFrom<$kind> for $name {
624 type Error = ();
625 fn try_from(elem: $kind) -> Result<$name, ()> {
626 let mut res = unsafe{Self::from_unchecked(elem)};
627 $(
628 if !res.$field().is_valid() {
629 return Err(());
630 }
631 )*
632 Ok(res)
633 }
634 }
635
636 #[allow(clippy::used_underscore_binding)]
637 impl $crate::BitStruct<{$(<$actual as $crate::ValidCheck<$kind>>::ALWAYS_VALID &&)* true}> for $name {
638 type Kind = $kind;
639
640 unsafe fn from_unchecked(inner: $kind) -> Self {
641 Self(unsafe {$crate::UnsafeStorage::new_unsafe(inner)})
642 }
643 }
644
645 #[allow(clippy::used_underscore_binding)]
646 impl $name {
647
648 unsafe fn from_unchecked(inner: $kind) -> Self {
649 Self(unsafe {$crate::UnsafeStorage::new_unsafe(inner)})
650 }
651
652 #[allow(clippy::too_many_arguments)]
653 pub fn new($($field: $actual),*) -> Self {
654 let mut res = unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) };
655 $(
656 res.$field().set($field);
657 )*
658 res
659 }
660
661 pub fn raw(self) -> $kind {
662 self.0.inner()
663 }
664
665 $crate::impl_fields!(<$kind as $crate::BitCount>::COUNT, $kind => $([$($field_meta),*], $field, $actual),*);
666 }
667
668 )*
669
670 $(
671 $crate::bit_struct_impl!(
672 $(#[$meta])*
673 $struct_vis struct $name ($kind) {
674 $(
675 $(#[$field_meta])*
676 $field: $actual
677 ),*
678 }
679
680 );
681 )*
682 };
683}
684
685#[doc(hidden)]
686#[macro_export]
687macro_rules! count_idents {
688 ($on: expr, [$head: ident $(,$xs: ident)*]) => {
689 $crate::count_idents!($on + 1, [$($xs),*])
690 };
691 ($on: expr, []) => {
692 $on
693 };
694}
695
696pub const fn bits(num: usize) -> usize {
708 const fn helper(count: usize, on: usize) -> usize {
710 if on > 0 {
713 helper(count + 1, on >> 1)
714 } else {
715 count
716 }
717 }
718
719 helper(0, num)
720}
721
722#[doc(hidden)]
724#[cfg(not(feature = "serde"))]
725#[macro_export]
726macro_rules! enum_serde_impl {
727 ($enum_vis:vis $name:ident { $fst_field:ident $(, $field:ident)* }) => {};
728}
729
730#[doc(hidden)]
732#[cfg(feature = "serde")]
733#[macro_export]
734macro_rules! enum_serde_impl {
735 ($name:ident { $($field:ident),* }) => {
736 impl $crate::serde::Serialize for $name {
737 fn serialize<S: $crate::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
738 match self {
739 $(
740 Self::$field => {
741 serializer.serialize_unit_variant(
742 stringify!($name),
743 *self as u32,
744 stringify!($field),
745 )
746 },
747 )*
748 }
749 }
750 }
751 impl<'de> $crate::serde::Deserialize<'de> for $name {
752 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: $crate::serde::Deserializer<'de> {
753 use ::core::{fmt, result::Result::{self, Ok, Err}, convert::TryFrom};
754 use $crate::serde::de::{Deserialize, Deserializer, EnumAccess, VariantAccess, Visitor};
755
756 #[repr(u64)]
757 enum Variants { $( $field ),* }
758 impl TryFrom<u64> for Variants {
759 type Error = ();
760
761 fn try_from(v: u64) -> Result<Self, Self::Error> {
762 if v < $crate::count_idents!(0, [$( $field ),*]) {
763 unsafe { core::mem::transmute(v) }
767 } else {
768 Err(())
769 }
770 }
771 }
772 impl<'de> Deserialize<'de> for Variants {
773 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
774 struct VariantsVisitor;
775 impl<'de> Visitor<'de> for VariantsVisitor {
776 type Value = Variants;
777 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
778 formatter.write_str("variant identifier")
779 }
780
781 fn visit_u64<E: $crate::serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
782 Variants::try_from(value)
783 .map_err(|()| $crate::serde::de::Error::invalid_value(
784 $crate::serde::de::Unexpected::Unsigned(value),
785 &"variant index"
786 ))
787 }
788
789 fn visit_str<E: $crate::serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
790 match value {
791 $( stringify!($field) => Ok(Variants::$field), )*
792 _ => Err($crate::serde::de::Error::unknown_variant(value, VARIANTS)),
793 }
794 }
795 }
796 deserializer.deserialize_identifier(VariantsVisitor)
797 }
798 }
799
800 struct EnumVisitor;
801 impl<'de> Visitor<'de> for EnumVisitor {
802 type Value = $name;
803 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
804 formatter.write_str(concat!("enum ", stringify!($name)))
805 }
806
807 fn visit_enum<A: EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
808 match data.variant()? {
809 $(
810 (Variants::$field, variant) => {
811 let () = variant.unit_variant()?;
812 Ok($name::$field)
813 }
814 ),*
815 }
816 }
817 }
818 const VARIANTS: &'static [&'static str] = &[ $( stringify!( $field ) ),* ];
819 deserializer.deserialize_enum(
820 stringify!($name),
821 VARIANTS,
822 EnumVisitor,
823 )
824 }
825 }
826 };
827}
828
829#[doc(hidden)]
831#[macro_export]
832macro_rules! enum_impl {
833 (FROMS $name: ident: [$($kind: ty),*]) => {
834 $(
835 impl From<$name> for $kind {
836 fn from(value: $name) -> Self {
837 Self::from(value as u8)
838 }
839 }
840 )*
841 };
842 (VALID_CORE $name: ident: [$($kind: ty),*]) => {
843 $(
844 unsafe impl $crate::ValidCheck<$kind> for $name {
845 const ALWAYS_VALID: bool = <Self as $crate::ValidCheck<u8>>::ALWAYS_VALID;
846 fn is_valid(value: $kind) -> bool {
847 Self::is_valid(value as u8)
848 }
849 }
850 )*
851 };
852 (COUNT $head:ident $(,$xs: ident)*) => {
853 1 + $crate::enum_impl!(COUNT $($xs),*)
854 };
855 (COUNT) => {
856 0
857 };
858 (VALID_BIT_STRUCT $name: ident: [$($kind: ty),*]) => {
859 $(
860 unsafe impl $crate::ValidCheck<$kind> for $name {
861 const ALWAYS_VALID: bool = <Self as $crate::ValidCheck<u8>>::ALWAYS_VALID;
862 fn is_valid(value: $kind) -> bool {
863 let inner = value.value();
864 Self::is_valid(inner as u8)
865 }
866 }
867 )*
868 };
869 (BITS_FIT_IN $name: ident: [$($kind: ty),+ $(,)?]) => {
870 $(
871 impl $crate::BitsFitIn<$kind> for $name {
872 fn fit(self) -> $kind {
873 (self as u8).fit()
874 }
875 }
876 )+
877 };
878 (FROM_IMPLS $name: ident) => {
879 $crate::enum_impl!(VALID_CORE $name: [u16, u32, u64, u128]);
880 $crate::enum_impl!(VALID_BIT_STRUCT $name: [$crate::u24, $crate::u40, $crate::u48, $crate::u56]);
881 $crate::enum_impl!(FROMS $name: [u8, u16, u32, u64, u128, $crate::u24, $crate::u40, $crate::u48, $crate::u56]);
882 $crate::enum_impl!(BITS_FIT_IN $name: [u8, u16, u32, u64, $crate::u24, $crate::u40, $crate::u48, $crate::u56]);
883
884 impl $crate::FieldStorage for $name {
885 type StoredType = u8;
886
887 fn inner_raw(self) -> Self::StoredType {
888 self as Self::StoredType
889 }
890 }
891
892 };
893 (
894 $(#[$meta:meta])*
895 $enum_vis: vis $name: ident($default: ident) {
896 $(#[$fst_field_meta:meta])*
897 $fst_field: ident
898 $(,
899 $(#[$field_meta:meta])*
900 $field: ident
901 )* $(,)?
902 }
903 ) => {
904 #[repr(u8)]
905 $(#[$meta])*
906 #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
907 $enum_vis enum $name {
908 $(#[$fst_field_meta])*
909 $fst_field,
910 $(
911 $(#[$field_meta])*
912 $field
913 ),*
914 }
915
916 $crate::enum_serde_impl! { $name { $fst_field $(, $field)* } }
917
918 unsafe impl $crate::BitCount for $name {
919 const COUNT: usize = $crate::bits($crate::count_idents!(0, [$($field),*]));
920 }
921
922 impl $name {
923 const VARIANT_COUNT: usize = $crate::enum_impl!(COUNT $fst_field $(,$field)*);
924 }
925
926 unsafe impl $crate::ValidCheck<u8> for $name {
927 const ALWAYS_VALID: bool = Self::VARIANT_COUNT.count_ones() == 1;
928 fn is_valid(value: u8) -> bool {
929 if (value as usize) < Self::VARIANT_COUNT {
930 true
931 } else {
932 false
933 }
934 }
935 }
936
937 $crate::enum_impl!(FROM_IMPLS $name);
938
939 impl Default for $name {
940 fn default() -> Self {
941 Self::$default
942 }
943 }
944
945 };
946
947
948 (
949 $(#[$meta:meta])*
950 $enum_vis: vis $name: ident {
951 $(#[$fst_field_meta:meta])*
952 $fst_field: ident
953 $(,
954 $(#[$field_meta:meta])*
955 $field: ident
956 )* $(,)?
957 }
958 ) => {
959 #[repr(u8)]
960 $(#[$meta])*
961 #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
962 $enum_vis enum $name {
963 $(#[$fst_field_meta])*
964 $fst_field,
965 $(
966 $(#[$field_meta])*
967 $field
968 ),*
969 }
970
971 $crate::enum_serde_impl! { $name { $fst_field $(, $field)* } }
972
973 impl Default for $name {
974 fn default() -> Self {
975 Self::$fst_field
976 }
977 }
978
979 impl $name {
980 const VARIANT_COUNT: usize = $crate::enum_impl!(COUNT $fst_field $(,$field)*);
981 }
982
983 unsafe impl $crate::BitCount for $name {
984 const COUNT: usize = $crate::bits($crate::count_idents!(0, [$($field),*]));
985 }
986
987
988 unsafe impl $crate::ValidCheck<u8> for $name {
989 const ALWAYS_VALID: bool = Self::VARIANT_COUNT.count_ones() == 1;
990
991 fn is_valid(value: u8) -> bool {
992 if (value as usize) < Self::VARIANT_COUNT {
993 true
994 } else {
995 false
996 }
997 }
998 }
999
1000 $crate::enum_impl!(FROM_IMPLS $name);
1001 };
1002}
1003
1004#[macro_export]
1033macro_rules! enums {
1034 (
1035 $(
1036 $(#[$meta:meta])*
1037 $enum_vis: vis $name: ident $(($enum_default: ident))? {
1038
1039 $(#[$fst_field_meta:meta])*
1040 $fst_field: ident
1041 $(,
1042 $(#[$field_meta:meta])*
1043 $field: ident
1044 )* $(,)?
1045 }
1046 )+
1047 ) => {
1048 $(
1049 $crate::enum_impl!(
1050 $(#[$meta])*
1051 $enum_vis $name $(($enum_default))? {
1052 $(#[$fst_field_meta])*
1053 $fst_field
1054 $(,
1055 $(#[$field_meta])*
1056 $field
1057 )*
1058 }
1059 );
1060 )+
1061 }
1062}
1063
1064#[macro_export]
1066macro_rules! create {
1067 (
1068 $struct_kind: ty {
1069 $($field: ident: $value: expr),* $(,)?
1070 }
1071 ) => {
1072 {
1073 let mut res = <$struct_kind>::of_defaults();
1074 $(
1075 res.$field().set($value);
1076 )*
1077 res
1078 }
1079 };
1080}