use std::collections::HashMap;
use serde::Deserialize;
use serde_tuple::Deserialize_tuple;
use super::{ItemType, RawCrateData, RawIndexData};
use crate::error::{Error, Result};
#[derive(Deserialize)]
struct RawIndex {
#[serde(flatten)]
crates: HashMap<String, RawCrate>,
}
#[derive(Deserialize)]
pub(super) struct RawCrate {
doc: String,
i: Vec<Entry>,
p: Vec<(ItemType, String)>,
}
impl From<RawCrate> for RawCrateData {
fn from(mut raw: RawCrate) -> Self {
RawCrateData {
doc: raw.doc,
t: raw.i.iter().map(|entry| entry.t).collect(),
n: raw
.i
.iter_mut()
.map(|entry| entry.n.take().unwrap_or_default())
.collect(),
q: raw
.i
.iter_mut()
.enumerate()
.filter_map(|(i, entry)| {
let q = entry.q.take().unwrap_or_default();
(!q.is_empty()).then_some((i, q))
})
.collect(),
d: raw
.i
.iter_mut()
.map(|entry| entry.d.take().unwrap_or_default())
.collect(),
i: raw
.i
.iter_mut()
.map(|entry| entry.i.unwrap_or_default())
.collect(),
p: raw.p,
}
}
}
#[derive(Deserialize_tuple)]
struct Entry {
t: ItemType,
n: Option<String>,
q: Option<String>,
d: Option<String>,
i: Option<usize>,
#[allow(dead_code)]
f: Option<Vec<serde_json::Value>>,
}
pub(super) fn load_raw(index: &str) -> Result<RawIndexData> {
let json = {
let mut json = index
.lines()
.filter_map(|l| {
if l.starts_with('"') {
l.strip_suffix('\\')
} else {
None
}
})
.fold(String::from("{"), |mut json, l| {
json.push_str(l);
json
});
json.push('}');
json.replace("\\\\\"", "\\\"")
.replace(r"\'", "'")
.replace(r"\\", r"\")
};
let raw = serde_json::from_str::<RawIndex>(&json).map_err(Error::from)?;
Ok(RawIndexData {
crates: raw
.crates
.into_iter()
.map(|(name, raw)| (name, raw.into()))
.collect(),
})
}