pinata_sdk/api/
metadata.rs

1use std::collections::HashMap;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Deserialize, Serialize)]
5#[serde(untagged)]
6/// Possible MetadaValues
7pub enum MetadataValue {
8  /// Represents a String metadata value
9  String(String),
10  /// Represents a float metadata value
11  Float(f64),
12  /// Represents an integer value
13  Integer(u64),
14  /// Only valid when used with a ChangePinMetadata request
15  Delete,
16}
17
18/// alias type for HashMap<String, MetadataValue>
19pub type MetadataKeyValues = HashMap<String, MetadataValue>;
20
21#[derive(Debug, Serialize)]
22/// Pin metadata stored along with files pinned.
23pub struct PinMetadata {
24  #[serde(skip_serializing_if = "Option::is_none")]
25  /// Custom name used for referencing your pinned content.
26  pub name: Option<String>,
27  /// List of key value items to attach with the pinned content
28  pub keyvalues: MetadataKeyValues,
29}
30
31#[derive(Debug, Deserialize)]
32/// Pin metadata returns from PinList query
33/// 
34/// This is different from [PinMetadata](struct.PinListMetadata.html) because
35/// keyvalues can also be optional in this result
36pub struct PinListMetadata {
37  /// Custom name used for referencing your pinned content.
38  pub name: Option<String>,
39  /// List of key value items to attach with the pinned content
40  pub keyvalues: Option<MetadataKeyValues>,
41}
42
43#[derive(Debug, Serialize)]
44#[serde(rename_all = "camelCase")]
45/// Pin metadata struct to update metadata of pinned items.
46/// 
47pub struct ChangePinMetadata {
48  /// Customx
49  pub ipfs_pin_hash: String,
50
51  #[serde(flatten)]
52  /// Updates to metadata for ipfs_pin_hash
53  pub metadata: PinMetadata,
54}
55
56#[cfg(test)]
57mod tests {
58  use std::collections::HashMap;
59  use serde_json::Value;
60  use super::{PinMetadata, MetadataValue};
61
62  #[test]
63  fn test_serialization_of_metadata() {
64    let mut keyvalues = HashMap::new();
65    keyvalues.insert("string".to_string(), MetadataValue::String("value".to_string()));
66    keyvalues.insert("number".to_string(), MetadataValue::Integer(10));
67    keyvalues.insert("delete".to_string(), MetadataValue::Delete);
68
69    let data = PinMetadata {
70      name: None,
71      keyvalues,
72    };
73
74    let json_value: Value = serde_json::from_str(
75      &serde_json::to_string(&data).unwrap()
76    ).unwrap();
77
78    // verify the structure of the json generated is similar to
79    // {
80    //   "keyvalues": {
81    //     "number": 10
82    //     "delete": Null,
83    //     "string": "value"
84    //   }
85    // }
86    if let Value::Object(object) = json_value {
87        if object.contains_key("name") {
88          assert!(false, "name fields of metadata should not exists")
89        }
90
91        if let Value::Object(keyvalues) = object.get("keyvalues").unwrap() {
92          if let Value::Null = keyvalues.get("delete").unwrap() { } else {
93            assert!(false, "keyvalues.delete should be null");
94          }
95
96          if let Value::String(string) = keyvalues.get("string").unwrap() {
97            assert_eq!("value", string);
98          } else {
99            assert!(false, "keyvalues.string is not a string");
100          }
101
102          if let Value::Number(number) = keyvalues.get("number").unwrap() {
103            assert_eq!(10, number.as_u64().unwrap());
104          } else {
105            assert!(false, "keyvalues.number is not a number");
106          }
107
108
109        } else {
110          assert!(false, "keyvalues fields of metadata should be an object");
111        }
112    } else {
113      assert!(false, "metadata not serialized as object");
114    }
115  }
116}