1use crate::error::{LocalError, LocalResult};
5use crate::types::pdu::*;
6
7use strum::IntoEnumIterator;
9use strum_macros::EnumIter;
10
11fn err(type_: &str, val: u32) -> LocalError {
13 LocalError::ProtocolError(format!("No bib1::{type_} found with value '{val}'"))
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
17pub enum Attribute {
18 Use = 1,
19 Relation,
20 Position,
21 Structure,
22 Truncation,
23 Completeness,
24 Sorting,
25}
26
27impl TryFrom<u32> for Attribute {
28 type Error = LocalError;
29 fn try_from(n: u32) -> LocalResult<Self> {
30 Self::iter()
31 .find(|a| *a as u32 == n)
32 .ok_or_else(|| err("Attribute", n))
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
37pub enum Use {
38 PersonalName = 1,
39 CorporateName,
40 ConferenceName,
41 Title,
42 TitleSeries,
43 TitleUniform,
44 Isbn,
45 Issn,
46 LcCardNumber,
47 BnbCardNumber,
48 BgfNumber,
49 LocalNumber,
50 DeweyClassification,
51 UdcClassification,
52 BlissClassification,
53 LcCallNumber,
54 NlmCallNumber,
55 NalCallNumber,
56 MosCallNumber,
57 LocalClassification,
58 SubjectHeading,
59 SubjectRameau,
60 BdiIndexSubject,
61 InspecSubject,
62 MeshSubject,
63 PaSubject,
64 LcSubjectHeading,
65 RvmSubjectHeading,
66 LocalSubjectIndex,
67 Date,
68 DateOfPublication,
69 DateOfAcquisition,
70 TitleKey,
71 TitleCollective,
72 TitleParallel,
73 TitleCover,
74 TitleAddedTitlePage,
75 TitleCaption,
76 TitleRunning,
77 TitleSpine,
78 TitleOtherVariant,
79 TitleFormer,
80 TitleAbbreviated,
81 TitleExpanded,
82 SubjectPrecis,
83 SubjectRswk,
84 SubjectSubdivision,
85 NumberNatlBiblio,
86 NumberLegalDeposit,
87 NumberGovtPub,
88 NumberMusicPublisher,
89 NumberDb,
90 NumberLocalCall,
91 CodeLanguage,
92 CodeGeographic,
93 CodeInstitution,
94 NameAndTitle,
95 NameGeographic,
96 PlacePublication,
97 Coden,
98 MicroformGeneration,
99 Abstract,
100 Note,
101 AuthorTitle = 1000,
102 RecordType,
103 Name,
104 Author,
105 AuthorNamePersonal,
106 AuthorNameCorporate,
107 AuthorNameConference,
108 IdentifierStandard,
109 SubjectLcChildrens,
110 SubjectNamePersonal,
111 BodyOfText,
112 DateTimeAddedToDb,
113 DateTimeLastModified,
114 AuthorityFormatId,
115 ConceptText,
116 ConceptReference,
117 Any,
118 ServerChoice,
119 Publisher,
120 RecordSource,
121 Editor,
122 BibLevel,
123 GeographicClass,
124 IndexedBy,
125 MapScale,
126 MusicKey,
127 RelatedPeriodical,
128 ReportNumber,
129 StockNumber,
130 ThematicNumber,
131 MaterialType,
132 DocId,
133 HostItem,
134 ContentType,
135 Anywhere,
136 AuthorTitleSubject,
137}
138
139impl From<Use> for AttributeElement {
140 fn from(u: Use) -> Self {
141 Self {
142 attribute_set: None,
143 attribute_type: Attribute::Use as u32,
144 attribute_value: AttributeValue::Numeric(u as u32),
145 }
146 }
147}
148
149impl TryFrom<u32> for Use {
150 type Error = LocalError;
151 fn try_from(n: u32) -> LocalResult<Self> {
152 Self::iter()
153 .find(|a| *a as u32 == n)
154 .ok_or_else(|| err("Use", n))
155 }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
159pub enum Relation {
160 LessThan = 1,
161 LessThanOrEqual,
162 Equal,
163 GreaterOrEqual,
164 GreaterThan,
165 NotEqual,
166 Phonetic = 100,
167 Stem,
168 Relevance,
169 AlwaysMatches,
170}
171
172impl TryFrom<u32> for Relation {
173 type Error = LocalError;
174 fn try_from(n: u32) -> LocalResult<Self> {
175 Self::iter()
176 .find(|a| *a as u32 == n)
177 .ok_or_else(|| err("Relation", n))
178 }
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
182pub enum Position {
183 FirstInField = 1,
184 FirstInSubfield,
185 AnyPositionInField,
186}
187
188impl TryFrom<u32> for Position {
189 type Error = LocalError;
190 fn try_from(n: u32) -> LocalResult<Self> {
191 Self::iter()
192 .find(|a| *a as u32 == n)
193 .ok_or_else(|| err("Position", n))
194 }
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
198pub enum Structure {
199 Phrase = 1,
200 Word,
201 Key,
202 Year,
203 DateNormalized,
204 WordList,
205 DateUnNormalized = 100,
206 NameNormalized,
207 NameUnNormalized,
208 Structure,
209 Urx,
210 FreeFormText,
211 DocumentText,
212 LocalNumber,
213 String,
214 NumericString,
215}
216
217impl TryFrom<u32> for Structure {
218 type Error = LocalError;
219 fn try_from(n: u32) -> LocalResult<Self> {
220 Self::iter()
221 .find(|a| *a as u32 == n)
222 .ok_or_else(|| err("Structure", n))
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
227pub enum Truncation {
228 RightTruncation = 1,
229 LeftTruncation,
230 LeftAndRightTruncation,
231 DoNotTruncate = 100,
232 Process,
233 RegExpr1,
234 RegExpr2,
235 ProcessAlt, }
237
238impl TryFrom<u32> for Truncation {
239 type Error = LocalError;
240 fn try_from(n: u32) -> LocalResult<Self> {
241 Self::iter()
242 .find(|a| *a as u32 == n)
243 .ok_or_else(|| err("Truncation", n))
244 }
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
248pub enum Completeness {
249 IncompleteSubfield = 1,
250 CompleteSubfield,
251 CompleteField,
252}
253
254impl TryFrom<u32> for Completeness {
255 type Error = LocalError;
256 fn try_from(n: u32) -> LocalResult<Self> {
257 Self::iter()
258 .find(|a| *a as u32 == n)
259 .ok_or_else(|| err("Completeness", n))
260 }
261}
262
263#[derive(Debug, Clone, Copy, PartialEq, EnumIter)]
264pub enum Sorting {
265 Ascending = 1,
266 Descending,
267}
268
269impl TryFrom<u32> for Sorting {
270 type Error = LocalError;
271 fn try_from(n: u32) -> LocalResult<Self> {
272 Self::iter()
273 .find(|a| *a as u32 == n)
274 .ok_or_else(|| err("Sorting", n))
275 }
276}
277
278pub fn stringify_attribute(a: &AttributeElement) -> LocalResult<String> {
296 let attr_type = Attribute::try_from(a.attribute_type)?;
297
298 let numeric_value = match &a.attribute_value {
299 AttributeValue::Numeric(n) => *n,
300 AttributeValue::Complex(c) => return Ok(format!("{attr_type:?}={c:?}")),
301 };
302
303 Ok(match attr_type {
304 Attribute::Use => format!("{attr_type:?}={:?}", Use::try_from(numeric_value)?),
305 Attribute::Relation => format!("{attr_type:?}={:?}", Relation::try_from(numeric_value)?),
306 Attribute::Position => format!("{attr_type:?}={:?}", Position::try_from(numeric_value)?),
307 Attribute::Structure => format!("{attr_type:?}={:?}", Structure::try_from(numeric_value)?),
308 Attribute::Truncation => {
309 format!("{attr_type:?}={:?}", Truncation::try_from(numeric_value)?)
310 }
311 Attribute::Completeness => {
312 format!("{attr_type:?}={:?}", Completeness::try_from(numeric_value)?)
313 }
314 Attribute::Sorting => format!("{attr_type:?}={:?}", Sorting::try_from(numeric_value)?),
315 })
316}