marc_rs/
record.rs

1/// MARC record structure
2#[derive(Debug, Clone, PartialEq)]
3pub struct Record {
4    pub leader: Leader,
5    pub control_fields: Vec<ControlField>,
6    pub data_fields: Vec<DataField>,
7}
8
9/// MARC leader (24 bytes)
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Leader {
12    pub record_length: u16,
13    pub record_status: char,
14    pub record_type: char,
15    pub bibliographic_level: char,
16    pub type_of_control: char,
17    pub character_coding_scheme: char,
18    pub indicator_count: u8,
19    pub subfield_code_count: u8,
20    pub base_address_of_data: u16,
21    pub encoding_level: char,
22    pub descriptive_cataloging_form: char,
23    pub multipart_resource_record_level: char,
24    pub length_of_length_of_field_portion: u8,
25    pub length_of_starting_character_position_portion: u8,
26    pub length_of_implementation_defined_portion: u8,
27    pub undefined: char,
28}
29
30impl Leader {
31    /// Create a new Leader from a 24-byte string
32    pub fn from_bytes(data: &[u8]) -> Result<Self, String> {
33        if data.len() != 24 {
34            return Err(format!("Leader must be 24 bytes, got {}", data.len()));
35        }
36
37        let record_length = parse_u16(&data[0..5])?;
38        let base_address = parse_u16(&data[12..17])?;
39
40        Ok(Leader {
41            record_length,
42            record_status: data[5] as char,
43            record_type: data[6] as char,
44            bibliographic_level: data[7] as char,
45            type_of_control: data[8] as char,
46            character_coding_scheme: data[9] as char,
47            indicator_count: data[10] - b'0',
48            subfield_code_count: data[11] - b'0',
49            base_address_of_data: base_address,
50            encoding_level: data[17] as char,
51            descriptive_cataloging_form: data[18] as char,
52            multipart_resource_record_level: data[19] as char,
53            length_of_length_of_field_portion: data[20] - b'0',
54            length_of_starting_character_position_portion: data[21] - b'0',
55            length_of_implementation_defined_portion: data[22] - b'0',
56            undefined: data[23] as char,
57        })
58    }
59
60    /// Convert Leader to 24-byte string
61    pub fn to_bytes(&self) -> Vec<u8> {
62        let mut bytes = vec![0u8; 24];
63        let record_length_str = format!("{:05}", self.record_length);
64        let base_address_str = format!("{:05}", self.base_address_of_data);
65
66        bytes[0..5].copy_from_slice(record_length_str.as_bytes());
67        bytes[5] = self.record_status as u8;
68        bytes[6] = self.record_type as u8;
69        bytes[7] = self.bibliographic_level as u8;
70        bytes[8] = self.type_of_control as u8;
71        bytes[9] = self.character_coding_scheme as u8;
72        bytes[10] = b'0' + self.indicator_count;
73        bytes[11] = b'0' + self.subfield_code_count;
74        bytes[12..17].copy_from_slice(base_address_str.as_bytes());
75        bytes[17] = self.encoding_level as u8;
76        bytes[18] = self.descriptive_cataloging_form as u8;
77        bytes[19] = self.multipart_resource_record_level as u8;
78        bytes[20] = b'0' + self.length_of_length_of_field_portion;
79        bytes[21] = b'0' + self.length_of_starting_character_position_portion;
80        bytes[22] = b'0' + self.length_of_implementation_defined_portion;
81        bytes[23] = self.undefined as u8;
82
83        bytes
84    }
85}
86
87fn parse_u16(bytes: &[u8]) -> Result<u16, String> {
88    let s = std::str::from_utf8(bytes).map_err(|e| format!("Invalid UTF-8: {}", e))?;
89    s.parse::<u16>().map_err(|e| format!("Invalid number: {}", e))
90}
91
92/// Control field (001-009)
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct ControlField {
95    pub tag: String,
96    pub value: String,
97}
98
99/// Data field (010-999)
100#[derive(Debug, Clone, PartialEq)]
101pub struct DataField {
102    pub tag: String,
103    pub ind1: char,
104    pub ind2: char,
105    pub subfields: Vec<Subfield>,
106}
107
108/// Subfield within a data field
109#[derive(Debug, Clone, PartialEq, Eq)]
110pub struct Subfield {
111    pub code: char,
112    pub value: String,
113}
114
115#[cfg(feature = "serde")]
116impl serde::Serialize for Record {
117    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118    where
119        S: serde::Serializer,
120    {
121        use serde::ser::SerializeStruct;
122        let mut state = serializer.serialize_struct("Record", 3)?;
123        state.serialize_field("leader", &self.leader)?;
124        state.serialize_field("control_fields", &self.control_fields)?;
125        state.serialize_field("data_fields", &self.data_fields)?;
126        state.end()
127    }
128}
129
130#[cfg(feature = "serde")]
131impl<'de> serde::Deserialize<'de> for Record {
132    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133    where
134        D: serde::Deserializer<'de>,
135    {
136        use serde::de::{self, MapAccess, Visitor};
137        use std::fmt;
138
139        struct RecordVisitor;
140
141        impl<'de> Visitor<'de> for RecordVisitor {
142            type Value = Record;
143
144            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
145                formatter.write_str("struct Record")
146            }
147
148            fn visit_map<V>(self, mut map: V) -> Result<Record, V::Error>
149            where
150                V: MapAccess<'de>,
151            {
152                let mut leader = None;
153                let mut control_fields = None;
154                let mut data_fields = None;
155
156                while let Some(key) = map.next_key()? {
157                    match key {
158                        "leader" => {
159                            if leader.is_some() {
160                                return Err(de::Error::duplicate_field("leader"));
161                            }
162                            leader = Some(map.next_value()?);
163                        }
164                        "control_fields" => {
165                            if control_fields.is_some() {
166                                return Err(de::Error::duplicate_field("control_fields"));
167                            }
168                            control_fields = Some(map.next_value()?);
169                        }
170                        "data_fields" => {
171                            if data_fields.is_some() {
172                                return Err(de::Error::duplicate_field("data_fields"));
173                            }
174                            data_fields = Some(map.next_value()?);
175                        }
176                        _ => {
177                            let _ = map.next_value::<de::IgnoredAny>()?;
178                        }
179                    }
180                }
181
182                Ok(Record {
183                    leader: leader.ok_or_else(|| de::Error::missing_field("leader"))?,
184                    control_fields: control_fields.ok_or_else(|| de::Error::missing_field("control_fields"))?,
185                    data_fields: data_fields.ok_or_else(|| de::Error::missing_field("data_fields"))?,
186                })
187            }
188        }
189
190        deserializer.deserialize_map(RecordVisitor)
191    }
192}
193
194#[cfg(feature = "serde")]
195impl serde::Serialize for Leader {
196    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
197    where
198        S: serde::Serializer,
199    {
200        use serde::ser::SerializeStruct;
201        let mut state = serializer.serialize_struct("Leader", 16)?;
202        state.serialize_field("record_length", &self.record_length)?;
203        state.serialize_field("record_status", &self.record_status)?;
204        state.serialize_field("record_type", &self.record_type)?;
205        state.serialize_field("bibliographic_level", &self.bibliographic_level)?;
206        state.serialize_field("type_of_control", &self.type_of_control)?;
207        state.serialize_field("character_coding_scheme", &self.character_coding_scheme)?;
208        state.serialize_field("indicator_count", &self.indicator_count)?;
209        state.serialize_field("subfield_code_count", &self.subfield_code_count)?;
210        state.serialize_field("base_address_of_data", &self.base_address_of_data)?;
211        state.serialize_field("encoding_level", &self.encoding_level)?;
212        state.serialize_field("descriptive_cataloging_form", &self.descriptive_cataloging_form)?;
213        state.serialize_field("multipart_resource_record_level", &self.multipart_resource_record_level)?;
214        state.serialize_field("length_of_length_of_field_portion", &self.length_of_length_of_field_portion)?;
215        state.serialize_field("length_of_starting_character_position_portion", &self.length_of_starting_character_position_portion)?;
216        state.serialize_field("length_of_implementation_defined_portion", &self.length_of_implementation_defined_portion)?;
217        state.serialize_field("undefined", &self.undefined)?;
218        state.end()
219    }
220}
221
222#[cfg(feature = "serde")]
223impl<'de> serde::Deserialize<'de> for Leader {
224    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
225    where
226        D: serde::Deserializer<'de>,
227    {
228        use serde::de::{self, MapAccess, Visitor};
229        use std::fmt;
230
231        struct LeaderVisitor;
232
233        impl<'de> Visitor<'de> for LeaderVisitor {
234            type Value = Leader;
235
236            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
237                formatter.write_str("struct Leader")
238            }
239
240            fn visit_map<V>(self, mut map: V) -> Result<Leader, V::Error>
241            where
242                V: MapAccess<'de>,
243            {
244                let mut record_length = None;
245                let mut record_status = None;
246                let mut record_type = None;
247                let mut bibliographic_level = None;
248                let mut type_of_control = None;
249                let mut character_coding_scheme = None;
250                let mut indicator_count = None;
251                let mut subfield_code_count = None;
252                let mut base_address_of_data = None;
253                let mut encoding_level = None;
254                let mut descriptive_cataloging_form = None;
255                let mut multipart_resource_record_level = None;
256                let mut length_of_length_of_field_portion = None;
257                let mut length_of_starting_character_position_portion = None;
258                let mut length_of_implementation_defined_portion = None;
259                let mut undefined = None;
260
261                while let Some(key) = map.next_key()? {
262                    match key {
263                        "record_length" => record_length = Some(map.next_value()?),
264                        "record_status" => record_status = Some(map.next_value()?),
265                        "record_type" => record_type = Some(map.next_value()?),
266                        "bibliographic_level" => bibliographic_level = Some(map.next_value()?),
267                        "type_of_control" => type_of_control = Some(map.next_value()?),
268                        "character_coding_scheme" => character_coding_scheme = Some(map.next_value()?),
269                        "indicator_count" => indicator_count = Some(map.next_value()?),
270                        "subfield_code_count" => subfield_code_count = Some(map.next_value()?),
271                        "base_address_of_data" => base_address_of_data = Some(map.next_value()?),
272                        "encoding_level" => encoding_level = Some(map.next_value()?),
273                        "descriptive_cataloging_form" => descriptive_cataloging_form = Some(map.next_value()?),
274                        "multipart_resource_record_level" => multipart_resource_record_level = Some(map.next_value()?),
275                        "length_of_length_of_field_portion" => length_of_length_of_field_portion = Some(map.next_value()?),
276                        "length_of_starting_character_position_portion" => length_of_starting_character_position_portion = Some(map.next_value()?),
277                        "length_of_implementation_defined_portion" => length_of_implementation_defined_portion = Some(map.next_value()?),
278                        "undefined" => undefined = Some(map.next_value()?),
279                        _ => {
280                            let _ = map.next_value::<de::IgnoredAny>()?;
281                        }
282                    }
283                }
284
285                Ok(Leader {
286                    record_length: record_length.ok_or_else(|| de::Error::missing_field("record_length"))?,
287                    record_status: record_status.ok_or_else(|| de::Error::missing_field("record_status"))?,
288                    record_type: record_type.ok_or_else(|| de::Error::missing_field("record_type"))?,
289                    bibliographic_level: bibliographic_level.ok_or_else(|| de::Error::missing_field("bibliographic_level"))?,
290                    type_of_control: type_of_control.ok_or_else(|| de::Error::missing_field("type_of_control"))?,
291                    character_coding_scheme: character_coding_scheme.ok_or_else(|| de::Error::missing_field("character_coding_scheme"))?,
292                    indicator_count: indicator_count.ok_or_else(|| de::Error::missing_field("indicator_count"))?,
293                    subfield_code_count: subfield_code_count.ok_or_else(|| de::Error::missing_field("subfield_code_count"))?,
294                    base_address_of_data: base_address_of_data.ok_or_else(|| de::Error::missing_field("base_address_of_data"))?,
295                    encoding_level: encoding_level.ok_or_else(|| de::Error::missing_field("encoding_level"))?,
296                    descriptive_cataloging_form: descriptive_cataloging_form.ok_or_else(|| de::Error::missing_field("descriptive_cataloging_form"))?,
297                    multipart_resource_record_level: multipart_resource_record_level.ok_or_else(|| de::Error::missing_field("multipart_resource_record_level"))?,
298                    length_of_length_of_field_portion: length_of_length_of_field_portion.ok_or_else(|| de::Error::missing_field("length_of_length_of_field_portion"))?,
299                    length_of_starting_character_position_portion: length_of_starting_character_position_portion
300                        .ok_or_else(|| de::Error::missing_field("length_of_starting_character_position_portion"))?,
301                    length_of_implementation_defined_portion: length_of_implementation_defined_portion.ok_or_else(|| de::Error::missing_field("length_of_implementation_defined_portion"))?,
302                    undefined: undefined.ok_or_else(|| de::Error::missing_field("undefined"))?,
303                })
304            }
305        }
306
307        deserializer.deserialize_map(LeaderVisitor)
308    }
309}
310
311#[cfg(feature = "serde")]
312impl serde::Serialize for ControlField {
313    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
314    where
315        S: serde::Serializer,
316    {
317        use serde::ser::SerializeStruct;
318        let mut state = serializer.serialize_struct("ControlField", 2)?;
319        state.serialize_field("tag", &self.tag)?;
320        state.serialize_field("value", &self.value)?;
321        state.end()
322    }
323}
324
325#[cfg(feature = "serde")]
326impl<'de> serde::Deserialize<'de> for ControlField {
327    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
328    where
329        D: serde::Deserializer<'de>,
330    {
331        use serde::de::{self, MapAccess, Visitor};
332        use std::fmt;
333
334        struct ControlFieldVisitor;
335
336        impl<'de> Visitor<'de> for ControlFieldVisitor {
337            type Value = ControlField;
338
339            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
340                formatter.write_str("struct ControlField")
341            }
342
343            fn visit_map<V>(self, mut map: V) -> Result<ControlField, V::Error>
344            where
345                V: MapAccess<'de>,
346            {
347                let mut tag = None;
348                let mut value = None;
349
350                while let Some(key) = map.next_key()? {
351                    match key {
352                        "tag" => {
353                            if tag.is_some() {
354                                return Err(de::Error::duplicate_field("tag"));
355                            }
356                            tag = Some(map.next_value()?);
357                        }
358                        "value" => {
359                            if value.is_some() {
360                                return Err(de::Error::duplicate_field("value"));
361                            }
362                            value = Some(map.next_value()?);
363                        }
364                        _ => {
365                            let _ = map.next_value::<de::IgnoredAny>()?;
366                        }
367                    }
368                }
369
370                Ok(ControlField {
371                    tag: tag.ok_or_else(|| de::Error::missing_field("tag"))?,
372                    value: value.ok_or_else(|| de::Error::missing_field("value"))?,
373                })
374            }
375        }
376
377        deserializer.deserialize_map(ControlFieldVisitor)
378    }
379}
380
381#[cfg(feature = "serde")]
382impl serde::Serialize for DataField {
383    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
384    where
385        S: serde::Serializer,
386    {
387        use serde::ser::SerializeStruct;
388        let mut state = serializer.serialize_struct("DataField", 4)?;
389        state.serialize_field("tag", &self.tag)?;
390        state.serialize_field("ind1", &self.ind1)?;
391        state.serialize_field("ind2", &self.ind2)?;
392        state.serialize_field("subfields", &self.subfields)?;
393        state.end()
394    }
395}
396
397#[cfg(feature = "serde")]
398impl<'de> serde::Deserialize<'de> for DataField {
399    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
400    where
401        D: serde::Deserializer<'de>,
402    {
403        use serde::de::{self, MapAccess, Visitor};
404        use std::fmt;
405
406        struct DataFieldVisitor;
407
408        impl<'de> Visitor<'de> for DataFieldVisitor {
409            type Value = DataField;
410
411            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
412                formatter.write_str("struct DataField")
413            }
414
415            fn visit_map<V>(self, mut map: V) -> Result<DataField, V::Error>
416            where
417                V: MapAccess<'de>,
418            {
419                let mut tag = None;
420                let mut ind1 = None;
421                let mut ind2 = None;
422                let mut subfields = None;
423
424                while let Some(key) = map.next_key()? {
425                    match key {
426                        "tag" => {
427                            if tag.is_some() {
428                                return Err(de::Error::duplicate_field("tag"));
429                            }
430                            tag = Some(map.next_value()?);
431                        }
432                        "ind1" => {
433                            if ind1.is_some() {
434                                return Err(de::Error::duplicate_field("ind1"));
435                            }
436                            ind1 = Some(map.next_value()?);
437                        }
438                        "ind2" => {
439                            if ind2.is_some() {
440                                return Err(de::Error::duplicate_field("ind2"));
441                            }
442                            ind2 = Some(map.next_value()?);
443                        }
444                        "subfields" => {
445                            if subfields.is_some() {
446                                return Err(de::Error::duplicate_field("subfields"));
447                            }
448                            subfields = Some(map.next_value()?);
449                        }
450                        _ => {
451                            let _ = map.next_value::<de::IgnoredAny>()?;
452                        }
453                    }
454                }
455
456                Ok(DataField {
457                    tag: tag.ok_or_else(|| de::Error::missing_field("tag"))?,
458                    ind1: ind1.ok_or_else(|| de::Error::missing_field("ind1"))?,
459                    ind2: ind2.ok_or_else(|| de::Error::missing_field("ind2"))?,
460                    subfields: subfields.ok_or_else(|| de::Error::missing_field("subfields"))?,
461                })
462            }
463        }
464
465        deserializer.deserialize_map(DataFieldVisitor)
466    }
467}
468
469#[cfg(feature = "serde")]
470impl serde::Serialize for Subfield {
471    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
472    where
473        S: serde::Serializer,
474    {
475        use serde::ser::SerializeStruct;
476        let mut state = serializer.serialize_struct("Subfield", 2)?;
477        state.serialize_field("code", &self.code)?;
478        state.serialize_field("value", &self.value)?;
479        state.end()
480    }
481}
482
483#[cfg(feature = "serde")]
484impl<'de> serde::Deserialize<'de> for Subfield {
485    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
486    where
487        D: serde::Deserializer<'de>,
488    {
489        use serde::de::{self, MapAccess, Visitor};
490        use std::fmt;
491
492        struct SubfieldVisitor;
493
494        impl<'de> Visitor<'de> for SubfieldVisitor {
495            type Value = Subfield;
496
497            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
498                formatter.write_str("struct Subfield")
499            }
500
501            fn visit_map<V>(self, mut map: V) -> Result<Subfield, V::Error>
502            where
503                V: MapAccess<'de>,
504            {
505                let mut code = None;
506                let mut value = None;
507
508                while let Some(key) = map.next_key()? {
509                    match key {
510                        "code" => {
511                            if code.is_some() {
512                                return Err(de::Error::duplicate_field("code"));
513                            }
514                            code = Some(map.next_value()?);
515                        }
516                        "value" => {
517                            if value.is_some() {
518                                return Err(de::Error::duplicate_field("value"));
519                            }
520                            value = Some(map.next_value()?);
521                        }
522                        _ => {
523                            let _ = map.next_value::<de::IgnoredAny>()?;
524                        }
525                    }
526                }
527
528                Ok(Subfield {
529                    code: code.ok_or_else(|| de::Error::missing_field("code"))?,
530                    value: value.ok_or_else(|| de::Error::missing_field("value"))?,
531                })
532            }
533        }
534
535        deserializer.deserialize_map(SubfieldVisitor)
536    }
537}