mrrc 0.7.6

A Rust library for reading, writing, and manipulating MARC bibliographic records in ISO 2709 binary format
Documentation
# Phase 3: Linked Field Navigation and Specialized Queries

## Overview
Phase 3 focuses on three key areas:
1. Linked field navigation (880 fields via subfield 6)
2. Authority control helpers
3. Format-specific query traits

---

### ⚠️ Current Status: GIL Release Investigation Ongoing

**Important Note:** Active investigation into GIL release performance issues is underway. See **@docs/history/GIL_RELEASE_INVESTIGATION_ADDENDUM.md** for:
- Root cause analysis (error handling in Phase 2)
- Critical issues identified in implementation
- Five new beads created to fix issues (mrrc-18s, mrrc-69r, mrrc-kzw, mrrc-5ph, mrrc-4rm)
- Critical path for fixes

Phase 3 planning may be affected by GIL release timeline. Consult the addendum for current status and dependencies.

---

## 1. Linked Field Navigation (880 Fields)

### Background: MARC 880 Fields
- **880**: Alternate Graphical Representation
- Used to link romanized/vernacular text with their original script versions
- Linkage via **subfield 6** (Linkage) in both the original field and the 880 field

### Subfield 6 Structure
Format: `NNN-XX` or `NNN-XX/r`
- `NNN`: Occurrence number (001-999) - links related fields
- `XX`: Script identification code
- `/r`: Reverse script flag (optional)

Example:
- Field 100: `$6 880-01` (occurrence 01)
- Field 880: `$6 100-01` (links back to 100)

### Implementation Plan

#### 1.1 Parse Linkage Occurrence
Create a utility to parse subfield 6:

```rust
pub struct LinkageInfo {
    pub occurrence: String,  // "01", "02", etc.
    pub script_id: String,   // "01" = Hebrew, "02" = Arabic, etc.
    pub is_reverse: bool,
}

impl LinkageInfo {
    pub fn from_subfield_6(value: &str) -> Option<Self> { ... }
}
```

#### 1.2 Field Linking Methods

Add to `Record`:

```rust
pub fn get_linked_field(&self, field: &Field) -> Option<&Field> {
    // Find the 880 field linked to this field
    // 1. Parse subfield 6 from field
    // 2. Find matching 880 field with same occurrence
}

pub fn get_all_linked_fields(&self, field: &Field) -> Vec<&Field> {
    // Get both original and 880 versions
    // Returns vector of 0-2 fields
}

pub fn get_field_pairs(&self, tag: &str) -> Vec<(&Field, Option<&Field>)> {
    // Get original field paired with its 880 counterpart (if exists)
}

pub fn get_880_fields(&self) -> impl Iterator<Item = &Field> {
    // Get all 880 fields
}

pub fn find_linked_by_occurrence(&self, occurrence: &str) -> Vec<&Field> {
    // Find all fields linked by occurrence number
}
```

#### 1.3 Bidirectional Lookup
- Original field (e.g., 100) has `$6 880-01`
- 880 field has `$6 100-01`
- Methods should work from either direction

### Implementation Strategy
1. Create `LinkageInfo` struct to parse subfield 6
2. Add `get_linked_field()` to Record
3. Add helper method to extract occurrence from subfield 6
4. Write comprehensive tests with realistic data

## 2. Authority Control Helpers

### Background: Authority Record Fields
- **4XX fields**: See From tracings (alternate forms)
- **5XX fields**: See Also tracings (related headings)
- **7XX fields**: Relationship information
- Field structure: same as regular fields (tag, indicators, subfields)

### Implementation Plan

#### 2.1 Authority Navigation Methods

Add to `AuthorityRecord`:

```rust
pub fn get_see_from_headings(&self) -> Vec<&Field> {
    // 4XX fields - non-preferred forms
}

pub fn get_see_also_headings(&self) -> Vec<&Field> {
    // 5XX fields - related terms
}

pub fn get_relationship_fields(&self) -> Vec<&Field> {
    // 7XX fields - authority relationships
}

pub fn get_authority_references(&self) -> Vec<&Field> {
    // All reference/tracing fields (4XX, 5XX, 7XX)
}
```

#### 2.2 Query Helpers

```rust
pub fn find_related_heading(&self, heading: &Field) -> Option<&Field> {
    // Find a related authority heading from 5XX
}

pub fn extract_authority_label(&field: &Field) -> Option<&str> {
    // Get $a subfield (preferred label)
}
```

## 3. Format-Specific Query Traits

### Goals
- Separate concerns for different record types
- Provide domain-specific helper methods
- Keep existing API unchanged

### Implementation Plan

#### 3.1 Trait Design

```rust
// For bibliographic records
pub trait BibliographicQueries {
    fn get_linked_field_pairs(&self) -> Vec<(&Field, Option<&Field>)>;
    fn get_all_880_fields(&self) -> Vec<&Field>;
}

// For authority records
pub trait AuthorityQueries {
    fn get_see_from_headings(&self) -> Vec<&Field>;
    fn get_see_also_headings(&self) -> Vec<&Field>;
    fn get_authority_references(&self) -> Vec<&Field>;
}

// For holdings records
pub trait HoldingsQueries {
    // Holdings-specific queries
}
```

#### 3.2 Implementation
- Implement `BibliographicQueries` for `Record`
- Implement `AuthorityQueries` for `AuthorityRecord`
- Implement `HoldingsQueries` for `HoldingsRecord`

## 4. Testing Strategy

### Test Data
Create sample MARC records with:
- Romanized/vernacular text linked via 880
- Authority records with 4XX, 5XX, 7XX fields
- Complex linking with multiple occurrence numbers
- Edge cases (missing linkage, malformed subfield 6)

### Test Coverage
1. **Linkage parsing**:
   - Parse valid `NNN-XX` format
   - Handle reverse script flag `/r`
   - Parse script ID codes
   - Reject invalid formats

2. **Field linking**:
   - Find 880 field from original
   - Find original from 880
   - Get field pairs
   - Handle non-existent links
   - Multiple occurrences

3. **Authority navigation**:
   - Extract see-from headings
   - Extract see-also headings
   - Extract relationship fields
   - Find related headings

4. **Format-specific traits**:
   - Bibliographic queries work on Record
   - Authority queries work on AuthorityRecord
   - Holdings queries work on HoldingsRecord

## Implementation Order

1. **Week 1**: Linked field navigation
   - LinkageInfo struct and parsing
   - get_linked_field() implementation
   - Basic tests

2. **Week 2**: Enhanced linking + Authority control
   - get_field_pairs() implementation
   - Authority helper methods
   - Authority tests

3. **Week 3**: Format-specific traits + Testing
   - Trait implementations
   - Comprehensive integration tests
   - Documentation

## Open Questions

1. Should we cache linkage information for performance?
2. How to handle malformed subfield 6 values?
3. Should we support additional linkage types beyond 880?
4. How deep should authority reference navigation go (just direct 4XX/5XX or also 7XX)?

## Success Criteria

- ✓ All linked field queries work bidirectionally
- ✓ Authority control methods handle all standard reference types
- ✓ Format-specific traits provide useful domain-specific queries
- ✓ 100+ comprehensive tests passing
- ✓ All quality gates passing (rustfmt, clippy, doc)
- ✓ No breaking changes to existing API