use std::str::FromStr;
use json_patch::Patch as JsonPatch;
use serde_json::Value as JsonValue;
pub(crate) const LONG_HELP: &str = "
Accepts both RFC6902 (JSON Patch) and RFC7396 (JSON Merge Patch) syntax.";
#[derive(Debug, thiserror::Error, miette::Diagnostic)]
#[error(transparent)]
#[remain::sorted]
pub(crate) enum Error {
Json(#[from] serde_json::Error),
Patch(#[from] json_patch::PatchError),
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(untagged)]
pub(crate) enum Patch {
RFC6902(JsonPatch),
RFC7396(JsonValue),
}
impl Patch {
pub(crate) fn apply<'doc>(&self, doc: &'doc mut JsonValue) -> Result<&'doc mut JsonValue, Error> {
match self {
Self::RFC6902(patch) => json_patch::patch(doc, patch)?,
Self::RFC7396(patch) => json_patch::merge(doc, patch),
}
Ok(doc)
}
}
impl From<JsonPatch> for Patch {
fn from(patch: JsonPatch) -> Self {
Self::RFC6902(patch)
}
}
impl From<JsonValue> for Patch {
fn from(value: JsonValue) -> Self {
if value.is_array() {
match serde_json::from_value(value.clone()) {
Ok(patch) => Self::RFC6902(patch),
Err(_) => Self::RFC7396(value),
}
} else {
Self::RFC7396(value)
}
}
}
impl FromStr for Patch {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(serde_json::from_str::<JsonValue>(s)?.into())
}
}