dpp/serialization/json/
safe_fields.rs

1/// Marker trait proving a type's u64/i64 fields are protected for JS-safe JSON serialization.
2///
3/// # How it works
4///
5/// The `#[json_safe_fields]` attribute macro auto-implements this trait for annotated types.
6/// The `#[derive(JsonConvertible)]` macro implements it for versioned enums and asserts
7/// that all inner variant types also implement it.
8///
9/// # Compile errors
10///
11/// If you see `` the trait `JsonSafeFields` is not satisfied ``, it means a field type
12/// in an annotated struct doesn't implement this trait. Fix it by one of:
13///
14/// - **Struct with u64 fields**: add `#[cfg_attr(feature = "json-conversion", json_safe_fields)]`
15/// - **Simple enum/struct without u64**: add `impl JsonSafeFields for MyType {}` below
16/// - **`BTreeMap<K, u64>` field**: add `#[serde(with = "json_safe_generic_u64_value_map")]`
17/// - **New `type Foo = u64` alias**: add it to `U64_ALIASES` in the proc macro crate
18///
19/// # Why u64/i64 don't implement this trait
20///
21/// A bare `u64` is NOT JS-safe. Safety comes from `#[serde(with = "json_safe_u64")]`
22/// applied at the field level. By excluding u64/i64 from this trait, the compiler
23/// catches unprotected type aliases (`type Foo = u64`) and containers (`Vec<u64>`)
24/// at compile time.
25pub trait JsonSafeFields {}
26
27// --- Primitive types (no u64/i64 risk) ---
28// NOTE: u64 and i64 are intentionally excluded — see trait doc above.
29
30impl JsonSafeFields for bool {}
31impl JsonSafeFields for u8 {}
32impl JsonSafeFields for u16 {}
33impl JsonSafeFields for u32 {}
34impl JsonSafeFields for i8 {}
35impl JsonSafeFields for i16 {}
36impl JsonSafeFields for i32 {}
37impl JsonSafeFields for f32 {}
38impl JsonSafeFields for f64 {}
39impl JsonSafeFields for usize {}
40impl JsonSafeFields for isize {}
41impl JsonSafeFields for char {}
42impl JsonSafeFields for String {}
43impl JsonSafeFields for () {}
44impl<T: JsonSafeFields> JsonSafeFields for &T {}
45impl<const N: usize> JsonSafeFields for [u8; N] {}
46
47// --- Standard collections (safe if inner types are safe) ---
48// NOTE: Vec<u64>, BTreeMap<K, u64> etc. will NOT satisfy these bounds because
49// u64 doesn't implement JsonSafeFields. Fields with such types must use a
50// custom `#[serde(with = "...")]` module (e.g., json_safe_u64_u64_map).
51
52impl<T: JsonSafeFields> JsonSafeFields for Vec<T> {}
53impl<T: JsonSafeFields> JsonSafeFields for Option<T> {}
54impl<T: JsonSafeFields> JsonSafeFields for Box<T> {}
55impl<K: JsonSafeFields, V: JsonSafeFields> JsonSafeFields for std::collections::BTreeMap<K, V> {}
56impl<T: JsonSafeFields> JsonSafeFields for std::collections::BTreeSet<T> {}
57impl<K: JsonSafeFields, V: JsonSafeFields> JsonSafeFields for std::collections::HashMap<K, V> {}
58impl<T: JsonSafeFields> JsonSafeFields for std::collections::HashSet<T> {}
59
60// --- Platform types (external, don't contain unprotected u64/i64) ---
61
62impl JsonSafeFields for platform_value::Identifier {}
63impl JsonSafeFields for platform_value::BinaryData {}
64impl JsonSafeFields for platform_value::Value {}
65impl JsonSafeFields for platform_value::string_encoding::Encoding {}
66
67// --- External crate types ---
68
69impl JsonSafeFields for dashcore::OutPoint {}
70
71// --- rs-dpp types that don't contain u64/i64 or have their own safe handling ---
72// Add new entries here when a json_safe_fields-annotated struct has a field whose
73// type is a simple enum/struct without u64/i64. The compiler will tell you which
74// type is missing via a `JsonSafeFields is not satisfied` error.
75
76impl JsonSafeFields
77    for crate::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers
78{
79}
80impl JsonSafeFields
81    for crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements
82{
83}
84impl JsonSafeFields
85    for crate::data_contract::associated_token::token_marketplace_rules::v0::TokenTradeMode
86{
87}
88impl JsonSafeFields for crate::data_contract::associated_token::token_perpetual_distribution::distribution_recipient::TokenDistributionRecipient {}
89impl JsonSafeFields for crate::identity::Purpose {}
90impl JsonSafeFields for crate::identity::SecurityLevel {}
91impl JsonSafeFields for crate::identity::KeyType {}
92impl JsonSafeFields for crate::block::epoch::Epoch {}
93impl JsonSafeFields for crate::identity::identity_public_key::IdentityPublicKey {}
94impl JsonSafeFields for crate::identity::state_transition::asset_lock_proof::AssetLockProof {}
95impl JsonSafeFields for crate::address_funds::PlatformAddress {}
96impl JsonSafeFields for crate::withdrawal::Pooling {}
97impl JsonSafeFields for crate::identity::core_script::CoreScript {}
98impl JsonSafeFields for crate::voting::votes::Vote {}
99impl JsonSafeFields for crate::voting::vote_choices::resource_vote_choice::ResourceVoteChoice {}
100impl JsonSafeFields for crate::group::action_event::GroupActionEvent {}
101// TokenEvent contains u64 aliases (TokenAmount, Credits) in tuple variants that
102// `#[json_safe_fields]` can't auto-annotate. Developer takes responsibility for
103// JS-safe serialization of these fields. See token_event.rs for details.
104impl JsonSafeFields for crate::tokens::token_event::TokenEvent {}