1use super::LexiconSource;
2use crate::lexicon::LexiconDoc;
3use jacquard_common::types::value::Data;
4use jacquard_common::IntoStatic;
5use miette::{IntoDiagnostic, Result};
6use serde::Deserialize;
7use std::collections::HashMap;
8use std::path::PathBuf;
9
10#[derive(Debug, Clone)]
11pub struct JsonFileSource {
12 pub path: PathBuf,
13}
14
15#[derive(Deserialize)]
16struct RecordsFile<'a> {
17 #[serde(borrow)]
18 records: Vec<Data<'a>>,
19}
20
21impl LexiconSource for JsonFileSource {
22 async fn fetch(&self) -> Result<HashMap<String, LexiconDoc<'_>>> {
23 let content = std::fs::read_to_string(&self.path).into_diagnostic()?;
24 let file: RecordsFile = serde_json::from_str(&content).into_diagnostic()?;
25
26 let mut lexicons = HashMap::new();
27
28 for record_data in file.records {
29 if let Some(doc) = Self::parse_lexicon_record(&record_data) {
30 let nsid = doc.id.to_string();
31 lexicons.insert(nsid, doc);
32 }
33 }
34
35 Ok(lexicons)
36 }
37}
38
39impl JsonFileSource {
40 fn parse_lexicon_record(record_data: &Data<'_>) -> Option<LexiconDoc<'static>> {
41 let value = match record_data {
42 Data::Object(map) => map.0.get("value")?,
43 _ => return None,
44 };
45
46 match serde_json::to_string(value) {
47 Ok(json) => match serde_json::from_str::<LexiconDoc>(&json) {
48 Ok(doc) => Some(doc.into_static()),
49 Err(e) => {
50 eprintln!("Warning: Failed to parse lexicon from record: {}", e);
51 None
52 }
53 },
54 Err(e) => {
55 eprintln!("Warning: Failed to serialize record value: {}", e);
56 None
57 }
58 }
59 }
60}