candid/types/
reference.rs1use super::principal::Principal;
7use super::{CandidType, Serializer, Type};
8use serde::de::{self, Deserialize, Visitor};
9use std::convert::TryFrom;
10use std::{fmt, io::Read};
11
12#[derive(PartialEq, Eq, Debug, Clone)]
13pub struct Func {
14 pub principal: Principal,
15 pub method: String,
16}
17#[derive(PartialEq, Eq, Debug, Clone)]
18pub struct Service {
19 pub principal: Principal,
20}
21
22#[macro_export]
23macro_rules! define_function {
27 ( $vis:vis $func:ident : $($ty:tt)+ ) => {
28 #[derive($crate::Deserialize, PartialEq, Eq, Debug, Clone)]
29 $vis struct $func(pub $crate::types::reference::Func);
30 impl $crate::CandidType for $func {
31 fn _ty() -> $crate::types::Type {
32 $crate::func!($($ty)+)
33 }
34 fn idl_serialize<S: $crate::types::Serializer>(&self, serializer: S) -> std::result::Result<(), S::Error>
35 {
36 self.0.idl_serialize(serializer)
37 }
38 }
39 impl From<$crate::types::reference::Func> for $func {
40 fn from(v: $crate::types::reference::Func) -> Self {
41 Self(v)
42 }
43 }
44 impl $func {
45 pub fn new(principal: $crate::Principal, method: String) -> Self {
46 $func($crate::types::reference::Func { principal, method })
47 }
48 }
49 }
50}
51#[macro_export]
52macro_rules! define_service {
56 ( $vis:vis $serv:ident : { $($ty:tt)* } ) => {
57 #[derive($crate::Deserialize, PartialEq, Eq, Debug, Clone)]
58 $vis struct $serv(pub $crate::types::reference::Service);
59 impl $crate::CandidType for $serv {
60 fn _ty() -> $crate::types::Type {
61 $crate::service!{$($ty)*}
62 }
63 fn idl_serialize<S: $crate::types::Serializer>(&self, serializer: S) -> std::result::Result<(), S::Error>
64 {
65 self.0.idl_serialize(serializer)
66 }
67 }
68 impl From<$crate::types::reference::Service> for $serv {
69 fn from(v: $crate::types::reference::Service) -> Self {
70 Self(v)
71 }
72 }
73 impl $serv {
74 pub fn new(principal: $crate::Principal) -> Self {
75 $serv($crate::types::reference::Service { principal })
76 }
77 }
78 }
79}
80
81impl CandidType for Func {
82 fn _ty() -> Type {
83 panic!("Cannot use Func directly. Use `define_function!` macro instead.")
84 }
85 fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
86 where
87 S: Serializer,
88 {
89 serializer.serialize_function(self.principal.as_slice(), &self.method)
90 }
91}
92impl CandidType for Service {
93 fn _ty() -> Type {
94 panic!("Cannot use Service directly. Use `define_service!` macro instead.")
95 }
96 fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
97 where
98 S: Serializer,
99 {
100 serializer.serialize_principal(self.principal.as_slice())
101 }
102}
103
104pub struct FuncVisitor;
106
107impl Visitor<'_> for FuncVisitor {
108 type Value = Func;
109 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
110 formatter.write_str("Func value")
111 }
112 fn visit_byte_buf<E: de::Error>(self, bytes: Vec<u8>) -> Result<Func, E> {
113 if bytes[0] != 5u8 {
114 return Err(de::Error::custom("not func"));
115 }
116 let mut bytes = &bytes[1..];
117 let len = leb128::read::unsigned(&mut bytes).map_err(E::custom)? as usize;
118 let mut buf = vec![0; len];
119 bytes.read_exact(&mut buf).map_err(E::custom)?;
120 let method = String::from_utf8(buf).map_err(E::custom)?;
121 let principal = Principal::try_from(bytes).map_err(E::custom)?;
122 Ok(Func { principal, method })
123 }
124}
125
126impl<'de> Deserialize<'de> for Func {
127 fn deserialize<D>(deserializer: D) -> Result<Func, D::Error>
128 where
129 D: serde::Deserializer<'de>,
130 {
131 deserializer.deserialize_any(FuncVisitor)
132 }
133}
134
135impl<'de> Deserialize<'de> for Service {
136 fn deserialize<D>(deserializer: D) -> Result<Service, D::Error>
137 where
138 D: serde::Deserializer<'de>,
139 {
140 struct ServVisitor;
141 impl Visitor<'_> for ServVisitor {
142 type Value = Service;
143 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
144 formatter.write_str("Service value")
145 }
146 fn visit_byte_buf<E: de::Error>(self, bytes: Vec<u8>) -> Result<Service, E> {
147 if bytes[0] != 4u8 {
148 return Err(de::Error::custom("not service"));
149 }
150 let bytes = &bytes[1..];
151 let principal = Principal::try_from(bytes).map_err(E::custom)?;
152 Ok(Service { principal })
153 }
154 }
155 deserializer.deserialize_any(ServVisitor)
156 }
157}