#![allow(clippy::impl_trait_in_params)]
use std::path::PathBuf;
use self_cell::MutBorrow;
use simd_json::BorrowedValue;
use super::{
ImportsExportsArrayGeneric, ImportsExportsEntryGeneric, ImportsExportsKind,
ImportsExportsMapGeneric, JsonObject, JsonValue, PackageJsonBackend, PackageJsonGeneric,
};
use crate::{FileSystem, JSONError, replace_bom_with_whitespace};
type BorrowedObject<'a> = simd_json::value::borrowed::Object<'a>;
self_cell::self_cell! {
pub struct PackageJsonCell {
owner: MutBorrow<Vec<u8>>,
#[covariant]
dependent: BorrowedValue,
}
}
pub type PackageJson = PackageJsonGeneric<PackageJsonCell>;
pub type ImportsExportsEntry<'a> = ImportsExportsEntryGeneric<'a, BorrowedValue<'a>>;
pub type ImportsExportsArray<'a> = ImportsExportsArrayGeneric<'a, BorrowedValue<'a>>;
pub type ImportsExportsMap<'a> = ImportsExportsMapGeneric<'a, BorrowedObject<'a>>;
impl<'a> JsonValue for BorrowedValue<'a> {
type Object = BorrowedObject<'a>;
fn as_str(&self) -> Option<&str> {
match self {
BorrowedValue::String(s) => Some(s.as_ref()),
_ => None,
}
}
fn as_bool(&self) -> Option<bool> {
match self {
BorrowedValue::Static(simd_json::StaticNode::Bool(b)) => Some(*b),
_ => None,
}
}
fn as_slice(&self) -> Option<&[Self]> {
match self {
BorrowedValue::Array(arr) => Some(arr.as_slice()),
_ => None,
}
}
fn as_object(&self) -> Option<&BorrowedObject<'a>> {
match self {
BorrowedValue::Object(obj) => Some(obj),
_ => None,
}
}
fn entry_kind(&self) -> ImportsExportsKind {
match self {
BorrowedValue::String(_) => ImportsExportsKind::String,
BorrowedValue::Array(_) => ImportsExportsKind::Array,
BorrowedValue::Object(_) => ImportsExportsKind::Map,
BorrowedValue::Static(_) => ImportsExportsKind::Invalid,
}
}
}
impl<'a> JsonObject for BorrowedObject<'a> {
type Value = BorrowedValue<'a>;
fn get(&self, key: &str) -> Option<&Self::Value> {
self.get(key)
}
fn iter(&self) -> impl Iterator<Item = (&str, &Self::Value)> {
self.iter().map(|(k, v)| (k.as_ref(), v))
}
}
impl PackageJsonBackend for PackageJsonCell {
type Value<'a> = BorrowedValue<'a>;
fn root(&self) -> &Self::Value<'_> {
self.borrow_dependent()
}
}
impl PackageJson {
pub fn parse(
fs: &dyn FileSystem,
path: PathBuf,
realpath: PathBuf,
json: Vec<u8>,
) -> Result<Self, JSONError> {
let mut json = json;
replace_bom_with_whitespace(&mut json);
super::check_if_empty(&json, &path)?;
let cell = PackageJsonCell::try_new(MutBorrow::new(json), |bytes| {
simd_json::to_borrowed_value(bytes.borrow_mut())
})
.map_err(|simd_error| {
let fallback_result = fs
.read(&realpath)
.map_err(|io_error| JSONError {
path: path.clone(),
message: format!("Failed to re-read file for error reporting: {io_error}"),
line: 0,
column: 0,
})
.and_then(|bytes| {
serde_json::from_slice::<serde_json::Value>(&bytes).map_err(|serde_error| {
JSONError {
path: path.clone(),
message: serde_error.to_string(),
line: serde_error.line(),
column: serde_error.column(),
}
})
});
match fallback_result {
Ok(_) => {
JSONError {
path: path.clone(),
message: format!("simd_json parse error: {simd_error}"),
line: 0,
column: 0,
}
}
Err(error) => error,
}
})?;
Ok(Self { path, realpath, store: cell })
}
}