//! Signal [`InlineIpld`] IPLD formatted [`Ipld`] use ipld_core::{cid::Cid, ipld, ipld::Ipld}; /// [Inline IPLD][spec] formatted [`Ipld`] /// /// This is helpful to indictate that spec-compliant inlining has already been performed. /// /// [Recall][spec] that the shape of Inline IPLD is either: /// /// ``` js /// {"/": {".": Ipld}} /// {"/": {".": Ipld, "&": Cid}} /// ``` /// /// [`InlineIpld`] can also be used directly in place of [`Ipld`] in [`ipld!`] macros. For example: /// /// ``` /// # use inline_ipld::{cid, ipld::inline::InlineIpld}; /// # use ipld_core::{ipld, ipld::Ipld}; /// # /// let inlined = InlineIpld {cid: None, ipld: ipld!([1, 2, 3])}; /// let dag = ipld!({"a": 1, "b": inlined}); /// assert_eq!(dag, ipld!({"a": 1, "b": {"/": {".": [1, 2, 3]}}})); /// ``` /// /// [spec]: https://github.com/ucan-wg/inline-ipld #[must_use] #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde-codec", derive(serde::Deserialize, serde::Serialize))] #[allow(clippy::module_name_repetitions)] pub struct InlineIpld { /// The [Ipld] to inline pub ipld: Ipld, /// An optional [Cid] to reference the inlined [Ipld] by pub cid: Option, } impl From for Ipld { fn from(inline: InlineIpld) -> Ipld { ipld!({ "/": match inline.cid { Some(link) => ipld!({".": inline.ipld, "&": link}), None => ipld!({".": inline.ipld}) } }) } } impl TryFrom for Cid { type Error = (); fn try_from(inline: InlineIpld) -> Result { inline.cid.ok_or(()) } } impl<'a> From<&'a InlineIpld> for &'a Ipld { fn from(inline: &'a InlineIpld) -> &'a Ipld { &inline.ipld } } impl InlineIpld { /// Tag some already-inlined [`Ipld`] to [`InlineIpld`] /// /// Use with caution: non-inlined [`Ipld`] can be maked as inlined with this function. /// /// This is used in place of [`from`][`From::from`] to highlight that no conversion or checks happen. /// If conversion is desired, use [`Self::new`] with the `cid` field set to [`None`]. /// /// # Arguments /// /// * `ipld` - [`Ipld`] that is already correctly inlined /// /// # Examples /// /// ``` /// # use inline_ipld::{cid, ipld::inline::InlineIpld}; /// # use std::str::FromStr; /// # use multihash_codetable::Code::Sha2_256; /// # use serde_ipld_dagcbor::codec::DagCborCodec; /// # use ipld_core::{ /// # cid::Version, /// # ipld, /// # ipld::Ipld, /// # cid::Cid /// # }; /// # /// let ready = ipld!({"a": 1, "b": {"/": {".": [1, 2, 3]}}}); /// let observed = InlineIpld::attest(ready.clone()); /// assert_eq!(Ipld::from(observed), ipld!({"/": {".": ready}})); /// ``` pub fn attest(ipld: Ipld) -> Self { InlineIpld { ipld, cid: None } } }