1use std::collections::{HashMap, HashSet};
2
3use crate::{
4 errors::{ChainsawError, ChainsawResult},
5 IdlProvider,
6};
7
8#[cfg(feature = "json")]
9mod json_uses {
10 pub use crate::json::{JsonAccountsDeserializer, JsonSerializationOpts};
11 pub use std::fmt::Write;
12}
13#[cfg(feature = "json")]
14use json_uses::*;
15
16#[cfg(feature = "bson")]
17mod bson_uses {
18 pub use crate::bson::{BsonAccountsDeserializer, BsonSerializationOpts};
19 pub use bson::raw::RawBson;
20}
21#[cfg(feature = "bson")]
22use bson_uses::*;
23
24pub struct ChainsawDeserializer<'opts> {
30 #[cfg(feature = "json")]
31 json_account_deserializers:
33 HashMap<String, JsonAccountsDeserializer<'opts>>,
34
35 #[cfg(feature = "json")]
37 json_serialization_opts: &'opts JsonSerializationOpts,
38
39 #[cfg(feature = "bson")]
40 bson_account_deserializers:
42 HashMap<String, BsonAccountsDeserializer<'opts>>,
43 #[cfg(feature = "bson")]
46 bson_serialization_opts: &'opts BsonSerializationOpts,
47}
48
49impl<'opts> ChainsawDeserializer<'opts> {
50 pub fn new(
56 #[cfg(feature = "json")]
57 json_serialization_opts: &'opts JsonSerializationOpts,
58 #[cfg(feature = "bson")]
59 bson_serialization_opts: &'opts BsonSerializationOpts,
60 ) -> Self {
61 Self {
62 #[cfg(feature = "json")]
63 json_account_deserializers: HashMap::new(),
64 #[cfg(feature = "json")]
65 json_serialization_opts,
66
67 #[cfg(feature = "bson")]
68 bson_account_deserializers: HashMap::new(),
69 #[cfg(feature = "bson")]
70 bson_serialization_opts,
71 }
72 }
73
74 pub fn add_idl_json(
77 &mut self,
78 program_id: String,
79 idl_json: &str,
80 provider: IdlProvider,
81 ) -> ChainsawResult<()> {
82 #[cfg(feature = "json")]
83 {
84 #[cfg(feature = "bson")]
85 let (provider, program_id) = (provider.clone(), program_id.clone());
86
87 let json_deserializer = JsonAccountsDeserializer::try_from_idl(
88 idl_json,
89 provider,
90 self.json_serialization_opts,
91 )?;
92 self.json_account_deserializers
93 .insert(program_id, json_deserializer);
94 }
95 #[cfg(feature = "bson")]
96 {
97 let bson_deserializer = BsonAccountsDeserializer::try_from_idl(
98 idl_json,
99 provider,
100 self.bson_serialization_opts,
101 )?;
102 self.bson_account_deserializers
103 .insert(program_id, bson_deserializer);
104 }
105 Ok(())
106 }
107
108 #[cfg(any(feature = "json", feature = "bson"))]
109 pub fn account_name(
110 &self,
111 program_id: &str,
112 discriminator: &crate::DiscriminatorBytes,
113 ) -> Option<&str> {
114 #[cfg(feature = "json")]
115 {
116 self.json_account_deserializers
117 .get(program_id)
118 .unwrap()
119 .account_name(discriminator)
120 }
121 #[cfg(all(feature = "bson", not(feature = "json")))]
122 {
123 self.bson_account_deserializers
124 .get(program_id)
125 .unwrap()
126 .account_name(discriminator)
127 }
128 }
129
130 #[cfg(any(feature = "json", feature = "bson"))]
132 pub fn has_idl(&self, program_id: &str) -> bool {
133 #[cfg(feature = "json")]
134 {
135 self.json_account_deserializers.contains_key(program_id)
136 }
137 #[cfg(all(feature = "bson", not(feature = "json")))]
138 {
139 self.bson_account_deserializers.contains_key(program_id)
140 }
141 }
142
143 #[cfg(any(feature = "json", feature = "bson"))]
145 pub fn added_idls(&self) -> HashSet<String> {
146 #[cfg(feature = "json")]
147 {
148 self.json_account_deserializers.keys().cloned().collect()
149 }
150 #[cfg(all(feature = "bson", not(feature = "json")))]
151 {
152 self.bson_account_deserializers.keys().cloned().collect()
153 }
154 }
155
156 #[cfg(feature = "json")]
165 pub fn deserialize_account_to_json_string(
166 &self,
167 program_id: &str,
168 account_data: &mut &[u8],
169 ) -> ChainsawResult<String> {
170 let mut f = String::new();
171 self.deserialize_account_to_json(program_id, account_data, &mut f)?;
172 Ok(f)
173 }
174
175 #[cfg(feature = "json")]
183 pub fn deserialize_account_to_json<W: Write>(
184 &self,
185 program_id: &str,
186 account_data: &mut &[u8],
187 f: &mut W,
188 ) -> ChainsawResult<()> {
189 let deserializer = self
190 .json_account_deserializers
191 .get(program_id)
192 .ok_or_else(|| {
193 ChainsawError::CannotFindAccountDeserializerForProgramId(
194 program_id.to_string(),
195 )
196 })?;
197
198 deserializer.deserialize_account_data(account_data, f)?;
199 Ok(())
200 }
201
202 #[cfg(feature = "bson")]
208 pub fn deserialize_account_to_bson(
209 &self,
210 program_id: &str,
211 account_data: &mut &[u8],
212 ) -> ChainsawResult<RawBson> {
213 let deserializer = self
214 .bson_account_deserializers
215 .get(program_id)
216 .ok_or_else(|| {
217 ChainsawError::CannotFindAccountDeserializerForProgramId(
218 program_id.to_string(),
219 )
220 })?;
221
222 deserializer.deserialize_account_data(account_data)
223 }
224}