#[cfg(test)]
mod test;
#[doc(hidden)]
pub const JSON_OID: sqlx::postgres::types::Oid = sqlx::postgres::types::Oid(114);
#[doc(hidden)]
pub const JSONB_OID: sqlx::postgres::types::Oid = sqlx::postgres::types::Oid(3802);
#[macro_export]
macro_rules! sqlx_json_decode {
    ($type:ty) => {
        impl<'r> sqlx::Decode<'r, sqlx::Postgres> for $type {
            fn decode(
                value: sqlx::postgres::PgValueRef<'r>,
            ) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
                let buf = $crate::decode_json(value)?;
                serde_json::from_slice(buf).map_err(Into::into)
            }
        }
        impl sqlx::Type<sqlx::Postgres> for $type {
            fn type_info() -> sqlx::postgres::PgTypeInfo {
                sqlx::postgres::PgTypeInfo::with_oid($crate::JSONB_OID)
            }
            fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool {
                *ty == sqlx::postgres::PgTypeInfo::with_oid($crate::JSONB_OID)
                    || *ty == sqlx::postgres::PgTypeInfo::with_oid($crate::JSON_OID)
            }
        }
    };
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BoxedRawValue(Box<serde_json::value::RawValue>);
#[cfg(feature = "schemars")]
impl schemars::JsonSchema for BoxedRawValue {
    fn is_referenceable() -> bool {
        false
    }
    fn schema_name() -> String {
        serde_json::value::RawValue::schema_name()
    }
    fn schema_id() -> std::borrow::Cow<'static, str> {
        serde_json::value::RawValue::schema_id()
    }
    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
        serde_json::value::RawValue::json_schema(gen)
    }
}
impl std::ops::Deref for BoxedRawValue {
    type Target = serde_json::value::RawValue;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl From<BoxedRawValue> for Box<serde_json::value::RawValue> {
    fn from(raw_value: BoxedRawValue) -> Self {
        raw_value.0
    }
}
impl<'r> sqlx::Decode<'r, sqlx::Postgres> for BoxedRawValue {
    fn decode(
        value: <sqlx::Postgres as sqlx::database::HasValueRef<'r>>::ValueRef,
    ) -> Result<Self, sqlx::error::BoxDynError> {
        let buf = decode_json(value)?;
        let string = std::str::from_utf8(buf)?;
        let raw_value = serde_json::value::RawValue::from_string(string.to_owned())?;
        Ok(BoxedRawValue(raw_value))
    }
}
impl sqlx::Type<sqlx::Postgres> for BoxedRawValue {
    fn type_info() -> sqlx::postgres::PgTypeInfo {
        sqlx::postgres::PgTypeInfo::with_oid(JSONB_OID)
    }
    fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool {
        *ty == sqlx::postgres::PgTypeInfo::with_oid(JSONB_OID)
            || *ty == sqlx::postgres::PgTypeInfo::with_oid(JSON_OID)
    }
}
pub fn decode_json(
    value: <sqlx::Postgres as sqlx::database::HasValueRef<'_>>::ValueRef,
) -> Result<&'_ [u8], sqlx::error::BoxDynError> {
    use sqlx::ValueRef;
    let is_jsonb = value.type_info().as_ref() == &sqlx::postgres::PgTypeInfo::with_oid(JSONB_OID);
    let mut buf = <&[u8] as sqlx::Decode<sqlx::Postgres>>::decode(value)?;
    if is_jsonb {
        assert_eq!(
            buf[0], 1,
            "unsupported JSONB format version {}; please open an issue",
            buf[0]
        );
        buf = &buf[1..];
    }
    Ok(buf)
}