1#![allow(non_snake_case)]
2use std::collections::HashMap;
7use std::error::Error;
8use serde::Deserialize;
13#[derive(Debug, Deserialize, Clone)]
18#[serde(untagged)]
19enum StringOrListOfStrings {
20 Abbreviation(String),
21 ListOfAbbreviations(Vec<String>),
22}
23
24#[derive(Debug, Deserialize, Clone)]
25struct ReferenceNumber(u16); #[derive(Debug, Deserialize, Clone)]
28struct AbbreviationEntry {
29 referenceNumber: ReferenceNumber,
31 referenceAbbreviation: String,
32}
33
34#[derive(Debug, Deserialize, Clone)]
35struct AbbreviationOrAbbreviationsEntry {
36 referenceNumber: ReferenceNumber,
38 referenceAbbreviationOrAbbreviations: StringOrListOfStrings,
39}
40
41#[derive(Debug, Deserialize, Clone)]
42struct USFMAbbreviationEntry {
43 referenceNumber: ReferenceNumber,
44 USFMAbbreviationOrAbbreviations: StringOrListOfStrings,
45 USFMNumberStringOrStrings: Option<StringOrListOfStrings>,
46}
47
48#[derive(Debug, Deserialize, Clone)]
49struct USFMNumberEntry {
50 referenceNumber: ReferenceNumber,
51 referenceAbbreviationOrAbbreviations: StringOrListOfStrings,
52 USFMAbbreviationOrAbbreviations: StringOrListOfStrings,
53}
54
55#[derive(Debug, Deserialize, Clone)]
56struct GeneralNumberEntry {
57 referenceNumber: ReferenceNumber,
59 referenceAbbreviation: String,
60 USFMAbbreviation: String,
61}
62
63#[derive(Debug, Deserialize, Clone)]
64struct ReferenceAbbreviationEntry {
65 referenceNumber: ReferenceNumber,
66 originalLanguageCode: String,
67 bookName: String,
68 shortAbbreviation: Option<String>,
69 SBLAbbreviation: Option<String>,
70 OSISAbbreviation: Option<String>,
71 SwordAbbreviation: Option<String>,
72 CCELNumberString: Option<String>,
73 USFMAbbreviation: Option<String>,
74 USFMNumberString: Option<String>,
75 USXNumberString: Option<String>,
76 UnboundCodeString: Option<String>,
77 BibleditNumberString: Option<String>,
78 NETBibleAbbreviation: Option<String>,
79 DrupalBibleAbbreviation: Option<String>,
80 ByzantineAbbreviation: Option<String>,
81 numExpectedChaptersString: Option<String>,
82 possibleAlternativeBooksList: Option<Vec<String>>,
83 bookNameEnglishGuide: String,
84 typicalSection: String,
85}
86
87#[derive(Debug, Deserialize, Clone)]
88struct ReferenceNumberEntry {
89 referenceAbbreviation: String,
90 originalLanguageCode: String,
91 bookName: String,
92 shortAbbreviation: Option<String>,
93 SBLAbbreviation: Option<String>,
94 OSISAbbreviation: Option<String>,
95 SwordAbbreviation: Option<String>,
96 CCELNumberString: Option<String>,
97 USFMAbbreviation: Option<String>,
98 USFMNumberString: Option<String>,
99 USXNumberString: Option<String>,
100 UnboundCodeString: Option<String>,
101 BibleditNumberString: Option<String>,
102 NETBibleAbbreviation: Option<String>,
103 DrupalBibleAbbreviation: Option<String>,
104 ByzantineAbbreviation: Option<String>,
105 numExpectedChaptersString: Option<String>,
106 possibleAlternativeBooksList: Option<Vec<String>>,
107 bookNameEnglishGuide: String,
108 typicalSection: String,
109}
110
111#[derive(Debug, Deserialize, Clone)]
112pub struct BibleBooksCodes { BibleWorksAbbreviationDict: HashMap<String, AbbreviationEntry>,
114 BibleditNumberDict: HashMap<String, GeneralNumberEntry>,
115 ByzantineAbbreviationDict: HashMap<String, AbbreviationEntry>,
116 CCELDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
117 DrupalBibleAbbreviationDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
118 EnglishNameDict: HashMap<String, AbbreviationEntry>,
119 NETBibleAbbreviationDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
120 OSISAbbreviationDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
121 SBLAbbreviationDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
122 SwordAbbreviationDict: HashMap<String, AbbreviationOrAbbreviationsEntry>,
123 USFMAbbreviationDict: HashMap<String, USFMAbbreviationEntry>,
124 USFMNumberDict: HashMap<String, USFMNumberEntry>,
125 USXNumberDict: HashMap<String, GeneralNumberEntry>,
126 UnboundCodeDict: HashMap<String, GeneralNumberEntry>,
127 allAbbreviationsDict: HashMap<String, String>,
128 referenceAbbreviationDict: HashMap<String, ReferenceAbbreviationEntry>,
129 referenceNumberDict: HashMap<String, ReferenceNumberEntry>,
130}
131
132impl BibleBooksCodes {
133 pub fn usfm_to_bbb(&self, usfm_bbb: &str) -> Result<String, Box<dyn Error>> {
134 if ! &self.USFMAbbreviationDict.contains_key(usfm_bbb) {
136 return Err("Invalid USFM abbreviation: '".to_owned() + usfm_bbb + "'")?; }
138 let bbbStringOrListOfStrings = &self.USFMAbbreviationDict[usfm_bbb].USFMAbbreviationOrAbbreviations;
139 match bbbStringOrListOfStrings {
140 StringOrListOfStrings::Abbreviation(bbb) => Ok(bbb.to_string()),
141 StringOrListOfStrings::ListOfAbbreviations(bbb_list) => Ok(bbb_list[0].to_string()),
142 }
143 }
144
145 pub fn usfm_num_to_usfm_abbrev(&self, usfm_num_str: &str) -> Result<String, Box<dyn Error>> {
146 if ! &self.USFMNumberDict.contains_key(usfm_num_str) {
148 return Err("Invalid USFM number: '".to_owned() + &usfm_num_str + "'")?; }
150 let bbbStringOrListOfStrings = &self.USFMNumberDict[usfm_num_str].USFMAbbreviationOrAbbreviations;
151 match bbbStringOrListOfStrings {
152 StringOrListOfStrings::Abbreviation(bbb) => Ok(bbb.to_string()),
153 StringOrListOfStrings::ListOfAbbreviations(bbb_list) => Ok(bbb_list[0].to_string()),
154 }
155 }
156
157 pub fn usfm_num_to_bbb(&self, usfm_num_str: &str) -> Result<String, Box<dyn Error>> {
158 if ! &self.USFMNumberDict.contains_key(usfm_num_str) {
160 return Err("Invalid USFM number: '".to_owned() + &usfm_num_str + "'")?; }
162 let bbbStringOrListOfStrings = &self.USFMNumberDict[usfm_num_str].referenceAbbreviationOrAbbreviations;
163 match bbbStringOrListOfStrings {
164 StringOrListOfStrings::Abbreviation(bbb) => Ok(bbb.to_string()),
165 StringOrListOfStrings::ListOfAbbreviations(bbb_list) => Ok(bbb_list[0].to_string()),
166 }
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 #[test]
173
174fn it_works() {
175 use crate::{load_from_json, BibleBooksCodes};
176 let data_folderpath = String::from("../");
178 let bible_books_codes: BibleBooksCodes = load_from_json(&data_folderpath).unwrap();
179 assert_eq!(bible_books_codes.referenceNumberDict["42"].referenceAbbreviation, "LUK");
180 assert_eq!(bible_books_codes.usfm_to_bbb("JAS").unwrap(), "JAM");
181 assert_eq!(bible_books_codes.usfm_num_to_usfm_abbrev("41").unwrap(), "Mat");
182 assert_eq!(bible_books_codes.usfm_num_to_bbb("42").unwrap(), "MRK");
183 }
184}
185
186
187pub fn load_from_json(data_folderpath: &String) -> Result<BibleBooksCodes, Box<dyn Error>> {
193 println!(" In bos_books_codes::load_from_json()…");
194
195 let the_file_contents = include_str!("BibleBooksCodes_Tables.json");
201 let bible_books_codes: BibleBooksCodes =
202 serde_json::from_str(&the_file_contents).expect("Books codes JSON was not well-formatted");
203 println!(" Loaded Bible books codes data for {:?} books.",
204 bible_books_codes.referenceNumberDict.len());
205 println!(" Book 42 is {:?}: {:?}",
206 bible_books_codes.referenceNumberDict["42"].referenceAbbreviation,
207 bible_books_codes.referenceNumberDict["42"].bookNameEnglishGuide);
208
209 Ok(bible_books_codes)
210}