You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
45 lines
1.4 KiB
45 lines
1.4 KiB
use crate::application::ports::DictSource; |
|
use crate::core::entities::{DictEntry, DictEntryId}; |
|
use serde::Deserialize; |
|
use std::fs::File; |
|
use std::io::BufReader; |
|
use std::path::Path; |
|
|
|
// The "Wire Format". |
|
// It exists ONLY here to map external JSON names to internal Entity names. |
|
#[derive(Deserialize)] |
|
struct JsonEntry { |
|
id: u32, |
|
word: String, // "word" in JSON, "text" in Entity |
|
// If JSON has extra fields we don't care about, Serde ignores them. |
|
} |
|
|
|
pub struct JsonFileDictSource { |
|
// Helper iterator from Serde |
|
iter: |
|
serde_json::StreamDeserializer<'static, serde_json::de::IoRead<BufReader<File>>, JsonEntry>, |
|
} |
|
|
|
impl JsonFileDictSource { |
|
pub fn new<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> { |
|
let file = File::open(path)?; |
|
let reader = BufReader::new(file); |
|
let iter = serde_json::Deserializer::from_reader(reader).into_iter::<JsonEntry>(); |
|
Ok(Self { iter }) |
|
} |
|
} |
|
|
|
impl DictSource for JsonFileDictSource { |
|
fn next_entry(&mut self) -> Option<Result<DictEntry, anyhow::Error>> { |
|
self.iter.next().map(|res| { |
|
match res { |
|
Ok(json) => { |
|
// MAPPING HAPPENS HERE. |
|
// This is type-safe. If DictEntry::new signature changes, this breaks. |
|
Ok(DictEntry::new(json.id as DictEntryId, json.word)) |
|
} |
|
Err(e) => Err(anyhow::Error::new(e)), |
|
} |
|
}) |
|
} |
|
}
|
|
|