Repository: astral-sh/uv
File: crates/uv-platform-tags/src/abi_tag.rs (Rust)

Code before:
    PartialEq,
    Ord,
    PartialOrd,
    Hash,
    rkyv::Archive,
    rkyv::Deserialize,
    rkyv::Serialize,
)]
#[rkyv(derive(Debug))]
#[repr(transparent)]
pub struct CPythonAbiModifiers(u8);

bitflags::bitflags! {
    impl CPythonAbiModifiers: u8 {
        /// A freethreading build of CPython without GIL, Python 3.13+.
        const Freethreading = 1 << 0;
        /// Historical, not needed on CPython 3.3+.
        const WideUnicode = 1 << 1;
        /// A debug build of CPython.
        const Debug = 1 << 2;
        /// Historical, not needed on CPython 3.4+, but only removed with CPython 3.8+.
        ///
        /// <https://github.com/python/cpython/issues/80888#issuecomment-1093821707>
        const Pymalloc = 1 << 3;
    }
}

impl Deref for CPythonAbiModifiers {
    type Target = u8;

    fn deref(&self) -> &u8 {
        &self.0
    }
}

impl DerefMut for CPythonAbiModifiers {
    fn deref_mut(&mut self) -> &mut u8 {
        &mut self.0
    }
}

impl Display for CPythonAbiModifiers {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        // Preserve the known order of flags, as observed from CPython itself.
        // TODO(konsti): Is there a canonical source for that?
        if self.contains(Self::Freethreading) {
            // https://peps.python.org/pep-0703/#build-configuration-changes
            // Python 3.13+ only, but it makes more sense to just rely on the sysconfig var.
            f.write_char('t')?;
        }
        if self.contains(Self::Debug) {

Review comment (suggestion):
If these will never have overlap, i.e. there will never be a flag like `Foo = 3 << 4`, then it's probably better to use `enumflags2` here like in `uv-preview`: https://github.com/astral-sh/uv/blob/cd4973623485aeda775d2721dddd95c269fa131b/crates/uv-preview/src/lib.rs

Code after:
    PartialEq,
    Ord,
    PartialOrd,
    Hash,
    rkyv::Archive,
    rkyv::Deserialize,
    rkyv::Serialize,
)]
#[rkyv(derive(Debug))]
#[repr(transparent)]
pub struct CPythonAbiVariants(u8);

bitflags::bitflags! {
    impl CPythonAbiVariants: u8 {
        /// A freethreading build of CPython without GIL, Python 3.13+.
        const Freethreading = 1 << 0;
        /// Historical, not needed on CPython 3.3+.
        const WideUnicode = 1 << 1;
        /// A debug build of CPython.
        const Debug = 1 << 2;
        /// Historical, not needed on CPython 3.4+, but only removed with CPython 3.8+.
        ///
        /// <https://github.com/python/cpython/issues/80888#issuecomment-1093821707>
        const Pymalloc = 1 << 3;
    }
}

impl Deref for CPythonAbiVariants {
    type Target = u8;

    fn deref(&self) -> &u8 {
        &self.0
    }
}

impl DerefMut for CPythonAbiVariants {
    fn deref_mut(&mut self) -> &mut u8 {
        &mut self.0
    }
}

impl Display for CPythonAbiVariants {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        // Preserve the known order of flags, as observed from CPython itself.
        // TODO(konsti): Is there a canonical source for that?
        if self.contains(Self::Freethreading) {
            // https://peps.python.org/pep-0703/#build-configuration-changes
            // Python 3.13+ only, but it makes more sense to just rely on the sysconfig var.
            f.write_char('t')?;
        }
        if self.contains(Self::Debug) {