1use move_core_types::account_address::AccountAddress;
5use move_core_types::annotated_visitor as AV;
6use move_core_types::language_storage::TypeTag;
7use move_core_types::u256::U256;
8
9use crate::balance::Balance;
10use crate::base_types::RESOLVED_STD_OPTION;
11use crate::base_types::move_ascii_str_layout;
12use crate::base_types::move_utf8_str_layout;
13use crate::base_types::url_layout;
14use crate::id::ID;
15use crate::id::UID;
16use crate::object::option_visitor as OV;
17
18pub trait Writer {
23 type Value;
24 type Error: std::error::Error
25 + From<Error>
26 + From<OV::Error>
27 + From<AV::Error>
28 + Send
29 + Sync
30 + 'static;
31
32 type Vec: Default;
33 type Map: Default;
34
35 type Nested<'a>: Writer<Value = Self::Value, Error = Self::Error, Vec = Self::Vec, Map = Self::Map>
36 where
37 Self: 'a;
38
39 fn nest(&mut self) -> Result<Self::Nested<'_>, Self::Error>;
42
43 fn write_null(&mut self) -> Result<Self::Value, Self::Error>;
45
46 fn write_bool(&mut self, value: bool) -> Result<Self::Value, Self::Error>;
48
49 fn write_number(&mut self, value: u32) -> Result<Self::Value, Self::Error>;
51
52 fn write_str(&mut self, value: String) -> Result<Self::Value, Self::Error>;
54
55 fn write_vec(&mut self, value: Self::Vec) -> Result<Self::Value, Self::Error>;
57
58 fn write_map(&mut self, value: Self::Map) -> Result<Self::Value, Self::Error>;
60
61 fn vec_push_element(
63 &mut self,
64 vec: &mut Self::Vec,
65 val: Self::Value,
66 ) -> Result<(), Self::Error>;
67
68 fn map_push_field(
70 &mut self,
71 map: &mut Self::Map,
72 key: String,
73 val: Self::Value,
74 ) -> Result<(), Self::Error>;
75}
76
77pub struct RpcVisitor<W: Writer> {
82 writer: W,
83}
84
85#[derive(thiserror::Error, Debug)]
86#[error("Unexpected type")]
87pub struct Error;
88
89impl<W: Writer> RpcVisitor<W> {
90 pub fn new(writer: W) -> Self {
92 Self { writer }
93 }
94}
95
96impl<'b, 'l, W: Writer> AV::Visitor<'b, 'l> for RpcVisitor<W> {
97 type Value = <W as Writer>::Value;
98 type Error = <W as Writer>::Error;
99
100 fn visit_u8(
101 &mut self,
102 _: &AV::ValueDriver<'_, 'b, 'l>,
103 value: u8,
104 ) -> Result<Self::Value, Self::Error> {
105 self.writer.write_number(value as u32)
106 }
107
108 fn visit_u16(
109 &mut self,
110 _: &AV::ValueDriver<'_, 'b, 'l>,
111 value: u16,
112 ) -> Result<Self::Value, Self::Error> {
113 self.writer.write_number(value as u32)
114 }
115
116 fn visit_u32(
117 &mut self,
118 _: &AV::ValueDriver<'_, 'b, 'l>,
119 value: u32,
120 ) -> Result<Self::Value, Self::Error> {
121 self.writer.write_number(value)
122 }
123
124 fn visit_u64(
125 &mut self,
126 _: &AV::ValueDriver<'_, 'b, 'l>,
127 value: u64,
128 ) -> Result<Self::Value, Self::Error> {
129 self.writer.write_str(value.to_string())
130 }
131
132 fn visit_u128(
133 &mut self,
134 _: &AV::ValueDriver<'_, 'b, 'l>,
135 value: u128,
136 ) -> Result<Self::Value, Self::Error> {
137 self.writer.write_str(value.to_string())
138 }
139
140 fn visit_u256(
141 &mut self,
142 _: &AV::ValueDriver<'_, 'b, 'l>,
143 value: U256,
144 ) -> Result<Self::Value, Self::Error> {
145 self.writer.write_str(value.to_string())
146 }
147
148 fn visit_bool(
149 &mut self,
150 _: &AV::ValueDriver<'_, 'b, 'l>,
151 value: bool,
152 ) -> Result<Self::Value, Self::Error> {
153 self.writer.write_bool(value)
154 }
155
156 fn visit_address(
157 &mut self,
158 _: &AV::ValueDriver<'_, 'b, 'l>,
159 value: AccountAddress,
160 ) -> Result<Self::Value, Self::Error> {
161 self.writer.write_str(value.to_canonical_string(true))
162 }
163
164 fn visit_signer(
165 &mut self,
166 _: &AV::ValueDriver<'_, 'b, 'l>,
167 value: AccountAddress,
168 ) -> Result<Self::Value, Self::Error> {
169 self.writer.write_str(value.to_canonical_string(true))
170 }
171
172 fn visit_vector(
173 &mut self,
174 driver: &mut AV::VecDriver<'_, 'b, 'l>,
175 ) -> Result<Self::Value, Self::Error> {
176 if driver.element_layout().is_type(&TypeTag::U8) {
177 use base64::{Engine, engine::general_purpose::STANDARD};
179
180 if let Some(bytes) = driver
181 .bytes()
182 .get(driver.position()..(driver.position() + driver.len() as usize))
183 {
184 let b64 = STANDARD.encode(bytes);
185 self.writer.write_str(b64)
186 } else {
187 Err(AV::Error::UnexpectedEof.into())
188 }
189 } else {
190 let mut elems = W::Vec::default();
191 {
192 let nested = self.writer.nest()?;
193 let mut visitor = RpcVisitor { writer: nested };
194
195 while let Some(elem) = driver.next_element(&mut visitor)? {
196 visitor.writer.vec_push_element(&mut elems, elem)?;
197 }
198 }
199
200 self.writer.write_vec(elems)
201 }
202 }
203
204 fn visit_struct(
205 &mut self,
206 driver: &mut AV::StructDriver<'_, 'b, 'l>,
207 ) -> Result<Self::Value, Self::Error> {
208 let ty = &driver.struct_layout().type_;
209 let layout = driver.struct_layout();
210
211 if layout == &move_ascii_str_layout()
212 || layout == &move_utf8_str_layout()
213 || layout == &url_layout()
214 {
215 let lo = driver.position();
218 driver.skip_field()?;
219 let hi = driver.position();
220
221 let bytes = &driver.bytes()[lo..hi];
223 let s: String = bcs::from_bytes(bytes).map_err(|_| Error)?;
224 self.writer.write_str(s)
225 } else if layout == &UID::layout() || layout == &ID::layout() {
226 let lo = driver.position();
229 driver.skip_field()?;
230 let hi = driver.position();
231
232 let bytes = &driver.bytes()[lo..hi];
234 let id = AccountAddress::from_bytes(bytes)
235 .map_err(|_| Error)?
236 .to_canonical_string(true);
237
238 self.writer.write_str(id)
239 } else if (&ty.address, ty.module.as_ref(), ty.name.as_ref()) == RESOLVED_STD_OPTION {
240 match OV::OptionVisitor(self).visit_struct(driver)? {
243 Some(value) => Ok(value),
244 None => self.writer.write_null(),
245 }
246 } else if Balance::is_balance_layout(layout) {
247 let lo = driver.position();
250 driver.skip_field()?;
251 let hi = driver.position();
252
253 let bytes = &driver.bytes()[lo..hi];
255 let balance = bcs::from_bytes::<u64>(bytes)
256 .map_err(|_| Error)?
257 .to_string();
258
259 self.writer.write_str(balance)
260 } else {
261 let mut map = W::Map::default();
264 {
265 let nested = self.writer.nest()?;
266 let mut visitor = RpcVisitor { writer: nested };
267
268 while let Some((field, elem)) = driver.next_field(&mut visitor)? {
269 let name = field.name.to_string();
270 visitor.writer.map_push_field(&mut map, name, elem)?;
271 }
272 }
273
274 self.writer.write_map(map)
275 }
276 }
277
278 fn visit_variant(
279 &mut self,
280 driver: &mut AV::VariantDriver<'_, 'b, 'l>,
281 ) -> Result<Self::Value, Self::Error> {
282 let mut map = W::Map::default();
283 {
284 let mut nested = self.writer.nest()?;
285
286 let variant = nested.write_str(driver.variant_name().to_string())?;
287 nested.map_push_field(&mut map, "@variant".to_owned(), variant)?;
288
289 let mut visitor = RpcVisitor { writer: nested };
290 while let Some((field, elem)) = driver.next_field(&mut visitor)? {
291 let name = field.name.to_string();
292 visitor.writer.map_push_field(&mut map, name, elem)?;
293 }
294 }
295
296 self.writer.write_map(map)
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use std::str::FromStr as _;
303
304 use move_core_types::annotated_value as A;
305 use move_core_types::ident_str;
306 use move_core_types::language_storage::StructTag;
307 use serde::Serialize;
308 use serde_json::Value;
309 use serde_json::json;
310
311 use super::*;
312
313 use A::MoveTypeLayout as L;
314
315 macro_rules! struct_ {
316 ($type:literal { $($name:literal : $layout:expr),* $(,)?}) => {
317 A::MoveTypeLayout::Struct(Box::new(A::MoveStructLayout {
318 type_: StructTag::from_str($type).expect("Failed to parse struct"),
319 fields: vec![$(A::MoveFieldLayout {
320 name: ident_str!($name).to_owned(),
321 layout: $layout,
322 }),*]
323 }))
324 }
325 }
326
327 macro_rules! vector_ {
328 ($inner:expr) => {
329 A::MoveTypeLayout::Vector(Box::new($inner))
330 };
331 }
332
333 struct JsonWriter;
334
335 #[derive(thiserror::Error, Debug)]
336 enum Error {
337 #[error(transparent)]
338 Visitor(#[from] AV::Error),
339
340 #[error("Unexpected type")]
341 UnexpectedType,
342 }
343
344 impl Writer for JsonWriter {
345 type Value = Value;
346 type Error = Error;
347
348 type Vec = Vec<Value>;
349 type Map = serde_json::Map<String, Value>;
350
351 type Nested<'a> = Self;
352
353 fn nest(&mut self) -> Result<Self::Nested<'_>, Self::Error> {
354 Ok(JsonWriter)
355 }
356
357 fn write_null(&mut self) -> Result<Self::Value, Self::Error> {
358 Ok(Value::Null)
359 }
360
361 fn write_bool(&mut self, value: bool) -> Result<Self::Value, Self::Error> {
362 Ok(Value::Bool(value))
363 }
364
365 fn write_number(&mut self, value: u32) -> Result<Self::Value, Self::Error> {
366 Ok(Value::Number(value.into()))
367 }
368
369 fn write_str(&mut self, value: String) -> Result<Self::Value, Self::Error> {
370 Ok(Value::String(value))
371 }
372
373 fn write_vec(&mut self, value: Self::Vec) -> Result<Self::Value, Self::Error> {
374 Ok(Value::Array(value))
375 }
376
377 fn write_map(&mut self, value: Self::Map) -> Result<Self::Value, Self::Error> {
378 Ok(Value::Object(value))
379 }
380
381 fn vec_push_element(
382 &mut self,
383 vec: &mut Self::Vec,
384 value: Self::Value,
385 ) -> Result<(), Self::Error> {
386 vec.push(value);
387 Ok(())
388 }
389
390 fn map_push_field(
391 &mut self,
392 map: &mut Self::Map,
393 key: String,
394 val: Self::Value,
395 ) -> Result<(), Self::Error> {
396 map.insert(key, val);
397 Ok(())
398 }
399 }
400
401 impl From<OV::Error> for Error {
402 fn from(OV::Error: OV::Error) -> Self {
403 Error::UnexpectedType
404 }
405 }
406
407 impl From<super::Error> for Error {
408 fn from(super::Error: super::Error) -> Self {
409 Error::UnexpectedType
410 }
411 }
412
413 fn json<T: Serialize>(layout: A::MoveTypeLayout, data: T) -> Value {
414 let bcs = bcs::to_bytes(&data).unwrap();
415 let mut visitor = RpcVisitor::new(JsonWriter);
416 A::MoveValue::visit_deserialize(&bcs, &layout, &mut visitor).unwrap()
417 }
418
419 fn address(a: &str) -> sui_sdk_types::Address {
420 sui_sdk_types::Address::from_str(a).unwrap()
421 }
422
423 #[test]
424 fn json_bool() {
425 let actual = json(L::Bool, true);
426 let expect = json!(true);
427 assert_eq!(actual, expect);
428
429 let actual = json(L::Bool, false);
430 let expect = json!(false);
431 assert_eq!(actual, expect);
432 }
433
434 #[test]
435 fn json_u8() {
436 let actual = json(L::U8, 42u8);
437 let expect = json!(42u8);
438 assert_eq!(expect, actual);
439 }
440
441 #[test]
442 fn json_u16() {
443 let actual = json(L::U16, 424u16);
444 let expect = json!(424u16);
445 assert_eq!(expect, actual);
446 }
447
448 #[test]
449 fn json_u32() {
450 let actual = json(L::U32, 432_432u32);
451 let expect = json!(432_432u32);
452 assert_eq!(expect, actual);
453 }
454
455 #[test]
456 fn json_u64() {
457 let actual = json(L::U64, 432_432_432_432u64);
458 let expect = json!(432_432_432_432u64.to_string());
459 assert_eq!(expect, actual);
460 }
461
462 #[test]
463 fn json_u128() {
464 let actual = json(L::U128, 424_242_424_242_424_242_424u128);
465 let expect = json!(424_242_424_242_424_242_424u128.to_string());
466 assert_eq!(expect, actual);
467 }
468
469 #[test]
470 fn json_u256() {
471 let actual = json(
472 L::U256,
473 U256::from_str("42424242424242424242424242424242424242424").unwrap(),
474 );
475 let expect = json!("42424242424242424242424242424242424242424");
476 assert_eq!(expect, actual);
477 }
478
479 #[test]
480 fn json_ascii_string() {
481 let l = struct_!("0x1::ascii::String" {
482 "bytes": vector_!(L::U8)
483 });
484 let actual = json(l, "The quick brown fox");
485 let expect = json!("The quick brown fox");
486 assert_eq!(expect, actual);
487 }
488
489 #[test]
490 fn json_utf8_string() {
491 let l = struct_!("0x1::string::String" {
492 "bytes": vector_!(L::U8)
493 });
494 let actual = json(l, "The quick brown fox");
495 let expect = json!("The quick brown fox");
496 assert_eq!(expect, actual);
497 }
498
499 #[test]
500 fn json_url() {
501 let l = struct_!("0x2::url::Url" {
502 "url": struct_!("0x1::ascii::String" {
503 "bytes": vector_!(L::U8)
504 })
505 });
506 let actual = json(l, "https://example.com");
507 let expect = json!("https://example.com");
508 assert_eq!(expect, actual);
509 }
510
511 #[test]
512 fn json_address() {
513 let actual = json(L::Address, address("0x42"));
514 let expect = json!(address("0x42").to_string());
515 assert_eq!(expect, actual);
516 }
517
518 #[test]
519 fn json_signer() {
520 let actual = json(L::Signer, address("0x42"));
521 let expect = json!(address("0x42").to_string());
522 assert_eq!(expect, actual);
523 }
524
525 #[test]
526 fn json_id() {
527 let l = struct_!("0x2::object::ID" {
528 "bytes": L::Address,
529 });
530 let actual = json(l, address("0x42"));
531 let expect = json!(address("0x42").to_string());
532 assert_eq!(expect, actual);
533 }
534
535 #[test]
536 fn json_uid() {
537 let l = struct_!("0x2::object::UID" {
538 "id": struct_!("0x2::object::ID" {
539 "bytes": L::Address,
540 })
541 });
542 let actual = json(l, address("0x42"));
543 let expect = json!(address("0x42").to_string());
544 assert_eq!(expect, actual);
545 }
546
547 #[test]
548 fn json_option() {
549 let l = struct_!("0x42::foo::Bar" {
550 "baz": struct_!("0x1::option::Option<u8>" { "vec": vector_!(L::U8) }),
551 });
552
553 let actual = json(l, Option::<Vec<u8>>::None);
554 let expect = json!({
555 "baz": null,
556 });
557 assert_eq!(expect, actual);
558 }
559
560 #[test]
561 fn json_balance() {
562 let l = struct_!("0x2::balance::Balance<0x2::sui::SUI>" {
563 "value": L::U64,
564 });
565
566 let actual = json(l, 100u64);
567 let expect = json!(100u64.to_string());
568 assert_eq!(expect, actual);
569 }
570
571 #[test]
572 fn json_compound() {
573 let l = struct_!("0x42::foo::Bar" {
574 "baz": struct_!("0x1::option::Option<u8>" { "vec": vector_!(L::U8) }),
575 "qux": vector_!(struct_!("0x43::xy::Zzy" {
576 "quy": L::U16,
577 "quz": struct_!("0x1::option::Option<0x1::ascii::String>" {
578 "vec": vector_!(struct_!("0x1::ascii::String" {
579 "bytes": vector_!(L::U8),
580 }))
581 }),
582 "frob": L::Address,
583 })),
584 });
585
586 let actual = json(
587 l,
588 (
589 Option::<Vec<u8>>::None,
590 vec![
591 (44u16, Some("Hello, world!"), address("0x45")),
592 (46u16, None, address("0x47")),
593 ],
594 ),
595 );
596 let expect = json!({
597 "baz": null,
598 "qux": [{
599 "quy": 44,
600 "quz": "Hello, world!",
601 "frob": address("0x45").to_string(),
602 },
603 {
604 "quy": 46,
605 "quz": null,
606 "frob": address("0x47").to_string(),
607 }
608 ],
609 });
610 assert_eq!(expect, actual);
611 }
612}