credential_exchange_format/
document.rs1use serde::{Deserialize, Serialize};
4
5use crate::{B64Url, EditableField, EditableFieldString, EditableFieldValue, Extension};
6
7#[derive(Clone, Debug, Default, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
9pub struct CustomFieldsCredential<E = ()> {
10 #[serde(default, skip_serializing_if = "Option::is_none")]
13 pub id: Option<B64Url>,
14 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub label: Option<String>,
18 pub fields: Vec<EditableFieldValue<E>>,
20 #[serde(default, skip_serializing_if = "Vec::is_empty")]
24 pub extensions: Vec<Extension<E>>,
25}
26
27#[derive(Clone, Debug, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct FileCredential {
34 pub id: B64Url,
36 pub name: String,
38 pub decrypted_size: u64,
40 pub integrity_hash: B64Url,
43}
44
45#[derive(Clone, Debug, Serialize, Deserialize)]
46#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
47pub struct NoteCredential<E = ()> {
48 pub content: EditableField<EditableFieldString, E>,
50}
51
52#[cfg(test)]
53mod tests {
54 use chrono::Month;
55 use serde_json::json;
56
57 use super::*;
58 use crate::{EditableFieldBoolean, EditableFieldString, EditableFieldYearMonth};
59
60 #[test]
61 fn test_serialize_custom_fields() {
62 let credential = CustomFieldsCredential {
63 id: None,
64 label: None,
65 fields: vec![
66 EditableFieldValue::<()>::String(EditableField {
67 id: Some(B64Url::from(b"field1".as_slice())),
68 value: EditableFieldString("hello".into()),
69 label: None,
70 extensions: None,
71 }),
72 EditableFieldValue::<()>::Boolean(EditableField {
73 id: None,
74 value: EditableFieldBoolean(false),
75 label: None,
76 extensions: None,
77 }),
78 ],
79 extensions: vec![],
80 };
81
82 let json = json!({
83 "fields": [
84 {
85 "id": "ZmllbGQx",
86 "fieldType": "string",
87 "value": "hello"
88 },
89 {
90 "fieldType": "boolean",
91 "value": "false"
92 }
93 ]
94 });
95
96 assert_eq!(serde_json::to_value(&credential).unwrap(), json);
97 }
98
99 #[test]
100 fn test_deserialize_custom_fields() {
101 let json = json!({
102 "fields": [
103 {
104 "fieldType": "string",
105 "value": "hello"
106 },
107 {
108 "fieldType": "concealed-string",
109 "value": "world"
110 },
111 {
112 "fieldType": "boolean",
113 "value": "false"
114 },
115 {
116 "fieldType": "year-month",
117 "value": "2025-02"
118 }
119 ]
120 });
121
122 let json = serde_json::to_string(&json).unwrap();
123 let credential: CustomFieldsCredential = serde_json::from_str(&json).unwrap();
124
125 assert_eq!(credential.id, None);
126 assert_eq!(credential.label, None);
127 assert_eq!(credential.extensions.len(), 0);
128 assert_eq!(credential.fields.len(), 4);
129
130 match &credential.fields[0] {
131 EditableFieldValue::String(field) => {
132 assert_eq!(field.value.0, "hello");
133 }
134 _ => panic!("Expected string field"),
135 }
136
137 match &credential.fields[1] {
138 EditableFieldValue::ConcealedString(field) => {
139 assert_eq!(field.value.0, "world");
140 }
141 _ => panic!("Expected concealed string field"),
142 }
143
144 match &credential.fields[2] {
145 EditableFieldValue::Boolean(field) => {
146 assert!(!field.value.0);
147 }
148 _ => panic!("Expected boolean field"),
149 }
150
151 match &credential.fields[3] {
152 EditableFieldValue::YearMonth(field) => {
153 assert_eq!(
154 field.value,
155 EditableFieldYearMonth {
156 year: 2025,
157 month: Month::February,
158 }
159 );
160 }
161 _ => panic!("Expected boolean field"),
162 }
163 }
164}