-
use std::convert::TryFrom;
+
use std::{convert::TryFrom, collections::BTreeMap};
+
pub use cml_core::{error::*, serialization::*};
+
use cml_crypto::{RawBytesEncoding, CryptoError};
+
use std::io::{Write, BufRead, Seek, SeekFrom};
+
use cbor_event::{se::Serializer, de::Deserializer};
metadata::{Metadata, TransactionMetadatum},
+
pub use cml_chain::{PolicyId, AssetName};
-
use crate::{CIP25Metadata, ChunkableString, LabelMetadata, String64};
+
use crate::{CIP25Metadata, ChunkableString, String64, MetadataDetails};
pub static CIP25_METADATA_LABEL: u64 = 721;
+
#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
+
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
+
pub struct LabelMetadata {
+
pub nfts: BTreeMap<PolicyId, BTreeMap<AssetName, MetadataDetails>>,
+
pub version: CIP25Version,
+
pub fn new(version: CIP25Version) -> Self {
+
pub fn set(&mut self, policy_id: PolicyId, asset_name: AssetName, details: MetadataDetails) -> Option<MetadataDetails> {
+
self.nfts.entry(policy_id).or_default().insert(asset_name, details)
+
pub fn get(&self, policy_id: &PolicyId, asset_name: &AssetName) -> Option<&MetadataDetails> {
+
self.nfts.get(policy_id)?.get(asset_name)
+
impl cbor_event::se::Serialize for LabelMetadata {
+
fn serialize<'se, W: Write>(
+
serializer: &'se mut Serializer<W>,
+
) -> cbor_event::Result<&'se mut Serializer<W>> {
+
serializer.write_map(cbor_event::Len::Len(self.nfts.len() as u64))?;
+
for (policy_id, assets) in self.nfts.iter() {
+
// hand-edit: write hex string
+
serializer.write_text(policy_id.to_hex())?;
+
serializer.write_map(cbor_event::Len::Len(assets.len() as u64))?;
+
for (asset_name, details) in assets.iter() {
+
// hand-edit: write hex string
+
serializer.write_text(hex::encode(asset_name.get()))?;
+
details.serialize(serializer)?;
+
serializer.write_map(cbor_event::Len::Len(2))?;
+
serializer.write_text(&"data")?;
+
serializer.write_map(cbor_event::Len::Len(self.nfts.len() as u64))?;
+
for (policy_id, assets) in self.nfts.iter() {
+
// hand-edit: write bytes
+
serializer.write_bytes(policy_id.to_raw_bytes())?;
+
serializer.write_map(cbor_event::Len::Len(assets.len() as u64))?;
+
for (asset_name, details) in assets.iter() {
+
// hand-edit: write bytes
+
serializer.write_bytes(asset_name.get())?;
+
details.serialize(serializer)?;
+
serializer.write_text(&"version")?;
+
serializer.write_unsigned_integer(2u64)?;
+
impl Deserialize for LabelMetadata {
+
fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
+
(|| -> Result<_, DeserializeError> {
+
// largely taken from result of generating the original CDDL then modifying to merge v1/v2
+
// this has to be modified anyway to allow for permissive parsing in the first place.
+
let initial_position = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
+
match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
+
let mut label_metadata_v1_table = BTreeMap::new();
+
let mut label_metadata_v1_table_len = 0;
+
let label_metadata_v1_len = raw.map()?;
+
while match label_metadata_v1_len {
+
cbor_event::Len::Len(n) => label_metadata_v1_table_len < n as usize,
+
cbor_event::Len::Indefinite => true,
+
match raw.cbor_type()? {
+
cbor_event::Type::Text => {
+
// hand-edit: read as hex text
+
let label_metadata_v1_key = PolicyId::from_hex(&raw.text()?)
+
.map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)))?;
+
let mut label_metadata_v1_value_table = BTreeMap::new();
+
let mut label_metadata_v1_value_table_len = 0;
+
let label_metadata_v1_value_len = raw.map()?;
+
while match label_metadata_v1_value_len {
+
cbor_event::Len::Len(n) => {
+
label_metadata_v1_value_table_len < n as usize
+
cbor_event::Len::Indefinite => true,
+
match raw.cbor_type()? {
+
cbor_event::Type::Text => {
+
// hand-edit: read as hex text
+
//let asset_bytes = hex::decode(raw.text()?)
+
// .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)))?;
+
let label_metadata_v1_value_key = AssetName::new(raw.text()?.as_bytes().to_vec())?;
+
let label_metadata_v1_value_value =
+
MetadataDetails::deserialize(raw)?;
+
if label_metadata_v1_value_table
+
label_metadata_v1_value_key.clone(),
+
label_metadata_v1_value_value,
+
return Err(DeserializeFailure::DuplicateKey(
+
"some complicated/unsupported type",
+
label_metadata_v1_value_table_len += 1;
+
cbor_event::Type::Special => {
+
assert_eq!(raw.special()?, cbor_event::Special::Break);
+
// we still need to read the data to move on to the CBOR after it
+
cml_core::metadata::TransactionMetadatum::deserialize(
+
cml_core::metadata::TransactionMetadatum::deserialize(
+
label_metadata_v1_value_table_len += 1;
+
let label_metadata_v1_value = label_metadata_v1_value_table;
+
if label_metadata_v1_table
+
.insert(label_metadata_v1_key.clone(), label_metadata_v1_value)
+
return Err(DeserializeFailure::DuplicateKey(Key::Str(
+
String::from("some complicated/unsupported type"),
+
label_metadata_v1_table_len += 1;
+
cbor_event::Type::Special => {
+
assert_eq!(raw.special()?, cbor_event::Special::Break);
+
// we still need to read the data to move on to the CBOR after it
+
cml_core::metadata::TransactionMetadatum::deserialize(raw)?;
+
cml_core::metadata::TransactionMetadatum::deserialize(raw)?;
+
label_metadata_v1_table_len += 1;