BAM Flags Type

Sources: SAM specification [SAM1] §1.4 (FLAG field), §4.2 (BAM binary FLAG). See References.

Motivation

BAM flags are a 16-bit bitfield with 12 defined bits. Raw u16 fields invite magic-number comparisons (flags & 0x4 != 0) scattered across the codebase, which are hard to read and easy to get wrong. A strongly-typed newtype prevents accidental mixing with other u16 values and provides self-documenting predicate methods.

Type definition

flags.type

BamFlags MUST be a #[repr(transparent)] newtype over u16.

flags.size

size_of::<BamFlags>() MUST equal size_of::<u16>() (2 bytes).

flags.copy

BamFlags MUST implement Copy, Clone, PartialEq, Eq, Hash, and Debug.

Construction

flags.from

BamFlags MUST implement From<u16> and Into<u16> (via From<BamFlags> for u16). These are the canonical conversions — all 16 bits are valid storage even if only 12 are currently assigned by the SAM spec.

flags.raw

BamFlags::raw(self) -> u16 MUST return the underlying value unchanged (convenience alias for u16::from).

flags.roundtrip

For all v: u16, BamFlags::from(v).raw() == v MUST hold.

flags.empty

BamFlags::empty() MUST return BamFlags(0) (no flags set).

Named constants

flags.constants

Named constants MUST be provided for all 12 SAM-defined flag bits:

ConstantValueSAM bitMeaning
FLAG_PAIRED0x00010x1Read is paired in sequencing
FLAG_PROPER_PAIR0x00020x2Read mapped in a proper pair
FLAG_UNMAPPED0x00040x4Read is unmapped
FLAG_MATE_UNMAPPED0x00080x8Mate is unmapped
FLAG_REVERSE0x00100x10Read on reverse strand
FLAG_MATE_REVERSE0x00200x20Mate on reverse strand
FLAG_FIRST_IN_TEMPLATE0x00400x40First in template
FLAG_SECOND_IN_TEMPLATE0x00800x80Last in template
FLAG_SECONDARY0x01000x100Secondary alignment
FLAG_FAILED_QC0x02000x200Failed quality checks
FLAG_DUPLICATE0x04000x400PCR or optical duplicate
FLAG_SUPPLEMENTARY0x08000x800Supplementary alignment

Predicates

flags.predicates

BamFlags MUST provide is_* predicate methods for every named constant. Each predicate MUST return self.0 & CONSTANT != 0.

flags.is_set

BamFlags::is_set(self, flag: u16) -> bool MUST test an arbitrary flag bit, enabling downstream code to check vendor-defined or future bits without needing a named method.

Mutators

Mutator and predicate methods accept raw u16 constants (not BamFlags) as the flag argument. This is intentional: named constants like FLAG_UNMAPPED are u16, and the SAM spec may add new bits or vendors may use currently-undefined bits. Accepting u16 keeps the API ergonomic (flags.is_set(FLAG_UNMAPPED)) without requiring a wrapping step for every constant.

flags.set

BamFlags::set(&mut self, flag: u16) MUST set the given bit(s): self.0 |= flag.

flags.unset

BamFlags::unset(&mut self, flag: u16) MUST clear the given bit(s): self.0 &= !flag.

flags.with

BamFlags::with(self, flag: u16) -> Self MUST return a copy with the given bit(s) set (builder-style, non-mutating).

flags.without

BamFlags::without(self, flag: u16) -> Self MUST return a copy with the given bit(s) cleared.

Bitwise operations

flags.bitor

BamFlags MUST implement BitOr<BamFlags> returning BamFlags, so flags can be combined: BamFlags::from(FLAG_PAIRED) | BamFlags::from(FLAG_REVERSE).

flags.bitor_assign

BamFlags MUST implement BitOrAssign<BamFlags> (|=).

flags.bitand

BamFlags MUST implement BitAnd<BamFlags> returning BamFlags, so flags can be intersected.

flags.bitand_assign

BamFlags MUST implement BitAndAssign<BamFlags> (&=).

Display

flags.display

Display for BamFlags MUST output the decimal u16 value (matching SAM text FLAG field format).

flags.format_traits

BamFlags MUST implement LowerHex, UpperHex, Octal, and Binary, all delegating to the underlying u16. This enables standard format strings ({:x}, {:#06x}, {:b}, etc.) to work identically to raw u16.

Field usage

flags.field_type

All BAM flag fields in the codebase (BamRecord, SlimRecord, OwnedBamRecord, PileupAlignment, ActiveRecord, ParsedHeader, etc.) MUST use BamFlags instead of raw u16. Exception: test helpers that construct raw BAM wire-format bytes (e.g. make_test_record) and comparison structs that mirror external library types (HtsRecord, SyntheticRead) MAY use u16 at the serialization/interop boundary.

flags.filter_signature

The pileup RecordFilter closure MUST accept BamFlags (not u16) as its first argument.