• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / bibdata / f2c03608-b062-443f-ac88-997e30ddf29a

21 Aug 2025 04:21PM UTC coverage: 91.316% (-0.3%) from 91.576%
f2c03608-b062-443f-ac88-997e30ddf29a

push

circleci

web-flow
Merge pull request #2884 from pulibrary/rust-permanent_location_code

Rewrite permanent_location_code in Rust

2 of 26 new or added lines in 3 files covered. (7.69%)

7413 of 8118 relevant lines covered (91.32%)

411.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/bibdata_rs/src/marc.rs
1
use magnus::exception;
2
use marctk::Record;
3

4
mod string_normalize;
5

6
pub mod control_field;
7
pub mod fixed_field;
8
pub mod genre;
9
pub mod identifier;
10
pub mod language;
11
pub mod note;
12
pub mod publication;
13
pub mod record_facet_mapping;
14
pub mod scsb;
15
pub mod variable_length_field;
16

17
pub use string_normalize::trim_punctuation;
18

19
pub fn alma_code_start_22(code: String) -> bool {
×
20
    code.starts_with("22") && code.ends_with("06421")
×
21
}
×
22
pub fn genres(record_string: String) -> Result<Vec<String>, magnus::Error> {
×
23
    let record = get_record(&record_string)?;
×
24
    Ok(genre::genres(&record))
×
25
}
×
26

27
pub fn original_languages_of_translation(
×
28
    record_string: String,
×
29
) -> Result<Vec<String>, magnus::Error> {
×
30
    let record = get_record(&record_string)?;
×
31
    Ok(language::original_languages_of_translation(&record)
×
32
        .iter()
×
33
        .map(|language| language.english_name.to_owned())
×
34
        .collect())
×
35
}
×
36

37
pub fn access_notes(record_string: String) -> Result<Option<Vec<String>>, magnus::Error> {
×
38
    let record = get_record(&record_string)?;
×
39
    Ok(note::access_notes(&record))
×
40
}
×
41

42
pub fn recap_partner_notes(record_string: String) -> Result<Vec<String>, magnus::Error> {
×
43
    let record = get_record(&record_string)?;
×
44
    Ok(scsb::recap_partner::recap_partner_notes(&record))
×
45
}
×
46

47
pub fn is_scsb(record_string: String) -> Result<bool, magnus::Error> {
×
48
    let record = get_record(&record_string)?;
×
49
    Ok(scsb::is_scsb(&record))
×
50
}
×
51

52
// Build the permanent location code from 852$b and 852$c
53
// Do not append the 852c if it is a SCSB - we save the SCSB locations as scsbnypl and scsbcul
NEW
54
pub fn permanent_location_code(field_string: String) -> Result<Option<String>, magnus::Error> {
×
NEW
55
    let record = get_record(&field_string)?;
×
NEW
56
    let field_852 = record.get_fields("852").into_iter().next();
×
NEW
57
    Ok(field_852.and_then(|field| match field.first_subfield("8") {
×
NEW
58
        Some(alma_code) if alma_code_start_22(alma_code.content().to_string()) => {
×
NEW
59
            let b = field
×
NEW
60
                .first_subfield("b")
×
NEW
61
                .map(|subfield| subfield.content())
×
NEW
62
                .unwrap_or_default();
×
NEW
63
            let c = field
×
NEW
64
                .first_subfield("c")
×
NEW
65
                .map(|subfield| subfield.content())
×
NEW
66
                .unwrap_or_default();
×
NEW
67
            Some(format!("{b}${c}"))
×
68
        }
NEW
69
        _ => field
×
NEW
70
            .first_subfield("b")
×
NEW
71
            .map(|subfield| subfield.content().to_string()),
×
NEW
72
    }))
×
NEW
73
}
×
74

75
pub fn current_location_code(field_string: String) -> Result<Option<String>, magnus::Error> {
×
76
    let record = get_record(&field_string)?;
×
77
    let field_876 = record.get_fields("876").into_iter().next();
×
78
    Ok(field_876.and_then(
×
79
        |field| match (field.first_subfield("y"), field.first_subfield("z")) {
×
80
            (Some(y), Some(z)) => Some(format!("{}${}", y.content(), z.content())),
×
81
            _ => None,
×
82
        },
×
83
    ))
84
}
×
85
pub fn format_facets(record_string: String) -> Result<Vec<String>, magnus::Error> {
×
86
    let record = get_record(&record_string)?;
×
87
    Ok(record_facet_mapping::format_facets(&record)
×
88
        .iter()
×
89
        .map(|facet| format!("{facet}"))
×
90
        .collect())
×
91
}
×
92
pub fn private_items(record_string: String, holding_id: String) -> Result<bool, magnus::Error> {
×
93
    let record = get_record(&record_string)?;
×
94
    let fields_876 = record.get_fields("876");
×
95
    let mut items = fields_876.iter().filter(|field| {
×
96
        field.first_subfield("0").map(|subfield| subfield.content()) == Some(&holding_id)
×
97
    });
×
98
    Ok(items.any(|item| {
×
99
        item.first_subfield("x")
×
100
            .map_or(true, |subfield| subfield.content() == "Private")
×
101
    }))
×
102
}
×
103

104
pub fn normalize_oclc_number(string: String) -> String {
×
105
    identifier::normalize_oclc_number(&string)
×
106
}
×
107

108
pub fn is_oclc_number(string: String) -> bool {
×
109
    identifier::is_oclc_number(&string)
×
110
}
×
111

112
pub fn identifiers_of_all_versions(record_string: String) -> Result<Vec<String>, magnus::Error> {
×
113
    let record = get_record(&record_string)?;
×
114
    Ok(identifier::identifiers_of_all_versions(&record))
×
115
}
×
116

117
pub fn publication_statements(record_string: String) -> Result<Vec<String>, magnus::Error> {
×
118
    let record = get_record(&record_string)?;
×
119
    Ok(publication::publication_statements(&record).collect())
×
120
}
×
121

122
pub fn strip_non_numeric(string: String) -> String {
×
123
    string_normalize::strip_non_numeric(&string)
×
124
}
×
125

126
fn get_record(breaker: &str) -> Result<Record, magnus::Error> {
×
127
    Record::from_breaker(breaker).map_err(|err| {
×
128
        magnus::Error::new(
×
129
            exception::runtime_error(),
×
130
            format!("Found error {} while parsing breaker {}", err, breaker),
×
131
        )
132
    })
×
133
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc