1use crate::parity_wasm::elements::{FunctionType, ValueType};
22use alloc::{borrow::ToOwned, collections::BTreeMap, string::String, vec::Vec};
23use core::iter;
24use enum_iterator::{self, Sequence};
25pub use pointers::*;
26
27#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Sequence, Hash)]
32pub enum SyscallName {
33 Send,
37 SendWGas,
38 SendCommit,
39 SendCommitWGas,
40 SendInit,
41 SendPush,
42 ReservationSend,
43 ReservationSendCommit,
44 SendInput,
45 SendPushInput,
46 SendInputWGas,
47
48 Reply,
50 ReplyWGas,
51 ReplyCommit,
52 ReplyCommitWGas,
53 ReplyPush,
54 ReservationReply,
55 ReservationReplyCommit,
56 ReplyInput,
57 ReplyPushInput,
58 ReplyInputWGas,
59
60 CreateProgram,
62 CreateProgramWGas,
63
64 Read,
66 ReplyTo,
67 SignalFrom,
68 Size,
69 ReplyCode,
70 SignalCode,
71 MessageId,
72 ProgramId,
73 Source,
74 Value,
75
76 EnvVars,
80 BlockHeight,
81 BlockTimestamp,
82 GasAvailable,
83 ValueAvailable,
84
85 Exit,
87 Leave,
88 Wait,
89 WaitFor,
90 WaitUpTo,
91 Wake,
92 Panic,
93 OomPanic,
94
95 Alloc,
97 Free,
98 FreeRange,
99 SystemBreak,
100
101 ReplyDeposit,
103 Debug,
104 Random,
105 ReserveGas,
106 UnreserveGas,
107 SystemReserveGas,
108}
109
110impl SyscallName {
111 pub fn to_str(&self) -> &'static str {
113 match self {
114 Self::Alloc => "alloc",
115 Self::EnvVars => "gr_env_vars",
116 Self::BlockHeight => "gr_block_height",
117 Self::BlockTimestamp => "gr_block_timestamp",
118 Self::CreateProgram => "gr_create_program",
119 Self::CreateProgramWGas => "gr_create_program_wgas",
120 Self::ReplyDeposit => "gr_reply_deposit",
121 Self::Debug => "gr_debug",
122 Self::Panic => "gr_panic",
123 Self::OomPanic => "gr_oom_panic",
124 Self::Exit => "gr_exit",
125 Self::Free => "free",
126 Self::FreeRange => "free_range",
127 Self::GasAvailable => "gr_gas_available",
128 Self::Leave => "gr_leave",
129 Self::MessageId => "gr_message_id",
130 Self::SystemBreak => "gr_system_break",
131 Self::ProgramId => "gr_program_id",
132 Self::Random => "gr_random",
133 Self::Read => "gr_read",
134 Self::Reply => "gr_reply",
135 Self::ReplyCommit => "gr_reply_commit",
136 Self::ReplyCommitWGas => "gr_reply_commit_wgas",
137 Self::ReplyPush => "gr_reply_push",
138 Self::ReplyTo => "gr_reply_to",
139 Self::SignalFrom => "gr_signal_from",
140 Self::ReplyWGas => "gr_reply_wgas",
141 Self::ReplyInput => "gr_reply_input",
142 Self::ReplyPushInput => "gr_reply_push_input",
143 Self::ReplyInputWGas => "gr_reply_input_wgas",
144 Self::ReservationReply => "gr_reservation_reply",
145 Self::ReservationReplyCommit => "gr_reservation_reply_commit",
146 Self::ReservationSend => "gr_reservation_send",
147 Self::ReservationSendCommit => "gr_reservation_send_commit",
148 Self::ReserveGas => "gr_reserve_gas",
149 Self::Send => "gr_send",
150 Self::SendCommit => "gr_send_commit",
151 Self::SendCommitWGas => "gr_send_commit_wgas",
152 Self::SendInit => "gr_send_init",
153 Self::SendPush => "gr_send_push",
154 Self::SendWGas => "gr_send_wgas",
155 Self::SendInput => "gr_send_input",
156 Self::SendPushInput => "gr_send_push_input",
157 Self::SendInputWGas => "gr_send_input_wgas",
158 Self::Size => "gr_size",
159 Self::Source => "gr_source",
160 Self::ReplyCode => "gr_reply_code",
161 Self::SignalCode => "gr_signal_code",
162 Self::SystemReserveGas => "gr_system_reserve_gas",
163 Self::UnreserveGas => "gr_unreserve_gas",
164 Self::Value => "gr_value",
165 Self::ValueAvailable => "gr_value_available",
166 Self::Wait => "gr_wait",
167 Self::WaitFor => "gr_wait_for",
168 Self::WaitUpTo => "gr_wait_up_to",
169 Self::Wake => "gr_wake",
170 }
171 }
172
173 pub fn all() -> impl Iterator<Item = Self> {
175 enum_iterator::all()
176 }
177
178 pub fn instrumentable() -> impl Iterator<Item = Self> {
181 Self::all().filter(|syscall| *syscall != Self::SystemBreak)
182 }
183
184 pub fn instrumentable_map() -> BTreeMap<String, SyscallName> {
186 Self::instrumentable()
187 .map(|syscall| (syscall.to_str().into(), syscall))
188 .collect()
189 }
190
191 pub fn signature(self) -> SyscallSignature {
193 use RegularParamType::*;
194
195 match self {
196 Self::Alloc => SyscallSignature::system(([Alloc], [ValueType::I32])),
197 Self::Free => SyscallSignature::system(([Free], [ValueType::I32])),
198 Self::FreeRange => SyscallSignature::system(([Free, FreeUpperBound], [ValueType::I32])),
199 Self::Debug => SyscallSignature::gr_infallible([
200 Ptr::SizedBufferStart {
201 length_param_idx: 1,
202 }
203 .into(),
204 Length,
205 ]),
206 Self::Panic => SyscallSignature::gr_infallible([
207 Ptr::SizedBufferStart {
208 length_param_idx: 1,
209 }
210 .into(),
211 Length,
212 ]),
213 Self::OomPanic => SyscallSignature::gr_infallible([]),
214 Self::BlockHeight => SyscallSignature::gr_infallible([Ptr::MutBlockNumber.into()]),
215 Self::BlockTimestamp => {
216 SyscallSignature::gr_infallible([Ptr::MutBlockTimestamp.into()])
217 }
218 Self::Exit => SyscallSignature::gr_infallible([Ptr::Hash(HashType::ActorId).into()]),
219 Self::GasAvailable => SyscallSignature::gr_infallible([Ptr::MutGas.into()]),
220 Self::ProgramId => {
221 SyscallSignature::gr_infallible([Ptr::MutHash(HashType::ActorId).into()])
222 }
223 Self::Leave => SyscallSignature::gr_infallible([]),
224 Self::ValueAvailable => SyscallSignature::gr_infallible([Ptr::MutValue.into()]),
225 Self::Wait => SyscallSignature::gr_infallible([]),
226 Self::WaitUpTo => SyscallSignature::gr_infallible([DurationBlockNumber]),
227 Self::WaitFor => SyscallSignature::gr_infallible([DurationBlockNumber]),
228 Self::Wake => SyscallSignature::gr_fallible((
229 [Ptr::Hash(HashType::MessageId).into(), DelayBlockNumber],
230 ErrPtr::ErrorCode,
231 )),
232 Self::ReplyCode => SyscallSignature::gr_fallible(ErrPtr::ErrorWithReplyCode),
233 Self::SignalCode => SyscallSignature::gr_fallible(ErrPtr::ErrorWithSignalCode),
234 Self::MessageId => {
235 SyscallSignature::gr_infallible([Ptr::MutHash(HashType::MessageId).into()])
236 }
237 Self::EnvVars => SyscallSignature::gr_infallible([Version, Ptr::MutBufferStart.into()]),
238 Self::Read => SyscallSignature::gr_fallible((
239 [
240 Offset,
241 Length,
242 Ptr::MutSizedBufferStart {
243 length_param_idx: 1,
244 }
245 .into(),
246 ],
247 ErrPtr::ErrorCode,
248 )),
249 Self::Reply => SyscallSignature::gr_fallible((
250 [
251 Ptr::SizedBufferStart {
252 length_param_idx: 1,
253 }
254 .into(),
255 Length,
256 Ptr::Value.into(),
257 ],
258 ErrPtr::ErrorWithHash(HashType::MessageId),
259 )),
260 Self::ReplyInput => SyscallSignature::gr_fallible((
261 [Offset, Length, Ptr::Value.into()],
262 ErrPtr::ErrorWithHash(HashType::MessageId),
263 )),
264 Self::ReplyWGas => SyscallSignature::gr_fallible((
265 [
266 Ptr::SizedBufferStart {
267 length_param_idx: 1,
268 }
269 .into(),
270 Length,
271 Gas,
272 Ptr::Value.into(),
273 ],
274 ErrPtr::ErrorWithHash(HashType::MessageId),
275 )),
276 Self::ReplyInputWGas => SyscallSignature::gr_fallible((
277 [Offset, Length, Gas, Ptr::Value.into()],
278 ErrPtr::ErrorWithHash(HashType::MessageId),
279 )),
280 Self::ReplyCommit => SyscallSignature::gr_fallible((
281 [Ptr::Value.into()],
282 ErrPtr::ErrorWithHash(HashType::MessageId),
283 )),
284 Self::ReplyCommitWGas => SyscallSignature::gr_fallible((
285 [Gas, Ptr::Value.into()],
286 ErrPtr::ErrorWithHash(HashType::MessageId),
287 )),
288 Self::ReservationReply => SyscallSignature::gr_fallible((
289 [
290 Ptr::HashWithValue(HashType::ReservationId).into(),
291 Ptr::SizedBufferStart {
292 length_param_idx: 2,
293 }
294 .into(),
295 Length,
296 ],
297 ErrPtr::ErrorWithHash(HashType::MessageId),
298 )),
299 Self::ReservationReplyCommit => SyscallSignature::gr_fallible((
300 [Ptr::HashWithValue(HashType::ReservationId).into()],
301 ErrPtr::ErrorWithHash(HashType::MessageId),
302 )),
303 Self::ReplyPush => SyscallSignature::gr_fallible((
304 [
305 Ptr::SizedBufferStart {
306 length_param_idx: 1,
307 }
308 .into(),
309 Length,
310 ],
311 ErrPtr::ErrorCode,
312 )),
313 Self::ReplyPushInput => {
314 SyscallSignature::gr_fallible(([Offset, Length], ErrPtr::ErrorCode))
315 }
316 Self::ReplyTo => {
317 SyscallSignature::gr_fallible(ErrPtr::ErrorWithHash(HashType::MessageId))
318 }
319 Self::SignalFrom => {
320 SyscallSignature::gr_fallible(ErrPtr::ErrorWithHash(HashType::MessageId))
321 }
322 Self::Send => SyscallSignature::gr_fallible((
323 [
324 Ptr::HashWithValue(HashType::ActorId).into(),
325 Ptr::SizedBufferStart {
326 length_param_idx: 2,
327 }
328 .into(),
329 Length,
330 DelayBlockNumber,
331 ],
332 ErrPtr::ErrorWithHash(HashType::MessageId),
333 )),
334 Self::SendInput => SyscallSignature::gr_fallible((
335 [
336 Ptr::HashWithValue(HashType::ActorId).into(),
337 Offset,
338 Length,
339 DelayBlockNumber,
340 ],
341 ErrPtr::ErrorWithHash(HashType::MessageId),
342 )),
343 Self::SendWGas => SyscallSignature::gr_fallible((
344 [
345 Ptr::HashWithValue(HashType::ActorId).into(),
346 Ptr::SizedBufferStart {
347 length_param_idx: 2,
348 }
349 .into(),
350 Length,
351 Gas,
352 DelayBlockNumber,
353 ],
354 ErrPtr::ErrorWithHash(HashType::MessageId),
355 )),
356 Self::SendInputWGas => SyscallSignature::gr_fallible((
357 [
358 Ptr::HashWithValue(HashType::ActorId).into(),
359 Offset,
360 Length,
361 Gas,
362 DelayBlockNumber,
363 ],
364 ErrPtr::ErrorWithHash(HashType::MessageId),
365 )),
366 Self::SendCommit => SyscallSignature::gr_fallible((
367 [
368 Handler,
369 Ptr::HashWithValue(HashType::ActorId).into(),
370 DelayBlockNumber,
371 ],
372 ErrPtr::ErrorWithHash(HashType::MessageId),
373 )),
374 Self::SendCommitWGas => SyscallSignature::gr_fallible((
375 [
376 Handler,
377 Ptr::HashWithValue(HashType::ActorId).into(),
378 Gas,
379 DelayBlockNumber,
380 ],
381 ErrPtr::ErrorWithHash(HashType::MessageId),
382 )),
383 Self::SendInit => SyscallSignature::gr_fallible(ErrPtr::ErrorWithHandle),
384 Self::SendPush => SyscallSignature::gr_fallible((
385 [
386 Handler,
387 Ptr::SizedBufferStart {
388 length_param_idx: 2,
389 }
390 .into(),
391 Length,
392 ],
393 ErrPtr::ErrorCode,
394 )),
395 Self::SendPushInput => {
396 SyscallSignature::gr_fallible(([Handler, Offset, Length], ErrPtr::ErrorCode))
397 }
398 Self::ReservationSend => SyscallSignature::gr_fallible((
399 [
400 Ptr::TwoHashesWithValue(HashType::ReservationId, HashType::ActorId).into(),
401 Ptr::SizedBufferStart {
402 length_param_idx: 2,
403 }
404 .into(),
405 Length,
406 DelayBlockNumber,
407 ],
408 ErrPtr::ErrorWithHash(HashType::MessageId),
409 )),
410 Self::ReservationSendCommit => SyscallSignature::gr_fallible((
411 [
412 Handler,
413 Ptr::TwoHashesWithValue(HashType::ReservationId, HashType::ActorId).into(),
414 DelayBlockNumber,
415 ],
416 ErrPtr::ErrorWithHash(HashType::MessageId),
417 )),
418 Self::Size => SyscallSignature::gr_infallible([Ptr::MutLength.into()]),
419 Self::Source => {
420 SyscallSignature::gr_infallible([Ptr::MutHash(HashType::ActorId).into()])
421 }
422 Self::Value => SyscallSignature::gr_infallible([Ptr::MutValue.into()]),
423 Self::CreateProgram => SyscallSignature::gr_fallible((
424 [
425 Ptr::HashWithValue(HashType::CodeId).into(),
426 Ptr::SizedBufferStart {
427 length_param_idx: 2,
428 }
429 .into(),
430 Length,
431 Ptr::SizedBufferStart {
432 length_param_idx: 4,
433 }
434 .into(),
435 Length,
436 DelayBlockNumber,
437 ],
438 ErrPtr::ErrorWithTwoHashes(HashType::MessageId, HashType::ActorId),
439 )),
440 Self::CreateProgramWGas => SyscallSignature::gr_fallible((
441 [
442 Ptr::HashWithValue(HashType::CodeId).into(),
443 Ptr::SizedBufferStart {
444 length_param_idx: 2,
445 }
446 .into(),
447 Length,
448 Ptr::SizedBufferStart {
449 length_param_idx: 4,
450 }
451 .into(),
452 Length,
453 Gas,
454 DelayBlockNumber,
455 ],
456 ErrPtr::ErrorWithTwoHashes(HashType::MessageId, HashType::ActorId),
457 )),
458 Self::ReplyDeposit => SyscallSignature::gr_fallible((
459 [Ptr::Hash(HashType::MessageId).into(), Gas],
460 ErrPtr::ErrorCode,
461 )),
462 Self::ReserveGas => SyscallSignature::gr_fallible((
463 [Gas, DurationBlockNumber],
464 ErrPtr::ErrorWithHash(HashType::ReservationId),
465 )),
466 Self::UnreserveGas => SyscallSignature::gr_fallible((
467 [Ptr::Hash(HashType::ReservationId).into()],
468 ErrPtr::ErrorWithGas,
469 )),
470 Self::SystemReserveGas => SyscallSignature::gr_fallible(([Gas], ErrPtr::ErrorCode)),
471 Self::Random => SyscallSignature::gr_infallible([
472 Ptr::Hash(HashType::SubjectId).into(),
473 Ptr::MutBlockNumberWithHash(HashType::SubjectId).into(),
474 ]),
475 Self::SystemBreak => unimplemented!("Unsupported syscall signature for system_break"),
476 }
477 }
478
479 pub fn returns_error(self) -> bool {
485 let signature = self.signature();
486
487 match &signature {
488 SyscallSignature::Fallible(_) | SyscallSignature::System(_) => true,
489 SyscallSignature::Infallible(_) => false,
490 }
491 }
492
493 pub fn is_fallible(self) -> bool {
499 self.signature().is_fallible()
500 }
501}
502
503#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
505pub enum ParamType {
506 Regular(RegularParamType),
507 Error(ErrPtr),
508}
509
510#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
515pub enum RegularParamType {
516 Length, Pointer(Ptr), Gas, Offset, DurationBlockNumber, DelayBlockNumber, Handler, Alloc, Free, FreeUpperBound, Version, }
528
529#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
533pub enum HashType {
534 ActorId,
535 CodeId,
536 MessageId,
537 ReservationId,
538 SubjectId,
540}
541
542impl From<ParamType> for ValueType {
543 fn from(value: ParamType) -> Self {
544 use RegularParamType::*;
545
546 match value {
547 ParamType::Regular(regular_ptr) => match regular_ptr {
548 Length | Pointer(_) | Offset | DurationBlockNumber | DelayBlockNumber | Handler
549 | Alloc | Free | FreeUpperBound | Version => ValueType::I32,
550 Gas => ValueType::I64,
551 },
552 ParamType::Error(_) => ValueType::I32,
553 }
554 }
555}
556
557#[derive(Debug, Clone, PartialEq, Eq, Hash)]
559pub enum SyscallSignature {
560 Fallible(FallibleSyscallSignature),
561 Infallible(InfallibleSyscallSignature),
562 System(SystemSyscallSignature),
563}
564
565impl SyscallSignature {
566 pub fn gr_fallible(fallible: impl Into<FallibleSyscallSignature>) -> Self {
567 Self::Fallible(fallible.into())
568 }
569
570 pub fn gr_infallible(infallible: impl Into<InfallibleSyscallSignature>) -> Self {
571 Self::Infallible(infallible.into())
572 }
573
574 pub fn system(system: impl Into<SystemSyscallSignature>) -> Self {
575 Self::System(system.into())
576 }
577
578 pub fn params(&self) -> &[ParamType] {
579 match self {
580 SyscallSignature::Fallible(fallible) => &fallible.0,
581 SyscallSignature::Infallible(infallible) => &infallible.0,
582 SyscallSignature::System(system) => &system.params,
583 }
584 }
585
586 pub fn results(&self) -> Option<&[ValueType]> {
587 match self {
588 SyscallSignature::Fallible(_) | SyscallSignature::Infallible(_) => None,
589 SyscallSignature::System(system) => Some(&system.results),
590 }
591 }
592
593 pub fn func_type(&self) -> FunctionType {
594 let (params, results) = match self {
595 SyscallSignature::Fallible(fallible) => (fallible.params(), Vec::new()),
596 SyscallSignature::Infallible(infallible) => (infallible.params(), Vec::new()),
597 SyscallSignature::System(system) => (system.params(), system.results().to_owned()),
598 };
599
600 FunctionType::new(params.iter().copied().map(Into::into).collect(), results)
601 }
602
603 pub fn is_fallible(&self) -> bool {
604 matches!(self, SyscallSignature::Fallible(_))
605 }
606
607 pub fn is_infallible(&self) -> bool {
608 matches!(self, SyscallSignature::Infallible(_))
609 }
610
611 pub fn is_system(&self) -> bool {
612 matches!(self, SyscallSignature::System(_))
613 }
614}
615
616#[derive(Debug, Clone, PartialEq, Eq, Hash)]
617pub struct FallibleSyscallSignature(Vec<ParamType>);
618
619impl FallibleSyscallSignature {
620 pub fn new<const N: usize>(params: [RegularParamType; N], err_ptr: ErrPtr) -> Self {
621 let params = params
622 .into_iter()
623 .map(ParamType::Regular)
624 .chain(iter::once(err_ptr.into()))
625 .collect();
626
627 FallibleSyscallSignature(params)
628 }
629
630 pub fn params(&self) -> &[ParamType] {
631 &self.0
632 }
633}
634
635impl<const N: usize> From<([RegularParamType; N], ErrPtr)> for FallibleSyscallSignature {
636 fn from((params, err_ptr): ([RegularParamType; N], ErrPtr)) -> Self {
637 FallibleSyscallSignature::new(params, err_ptr)
638 }
639}
640
641impl From<ErrPtr> for FallibleSyscallSignature {
642 fn from(err_ptr: ErrPtr) -> Self {
643 FallibleSyscallSignature::new([], err_ptr)
644 }
645}
646
647#[derive(Debug, Clone, PartialEq, Eq, Hash)]
648pub struct InfallibleSyscallSignature(Vec<ParamType>);
649
650impl InfallibleSyscallSignature {
651 pub fn new<const N: usize>(params: [RegularParamType; N]) -> Self {
652 InfallibleSyscallSignature(params.into_iter().map(ParamType::Regular).collect())
653 }
654
655 pub fn params(&self) -> &[ParamType] {
656 &self.0
657 }
658}
659
660impl<const N: usize> From<[RegularParamType; N]> for InfallibleSyscallSignature {
661 fn from(params: [RegularParamType; N]) -> Self {
662 InfallibleSyscallSignature::new(params)
663 }
664}
665
666#[derive(Debug, Clone, PartialEq, Eq, Hash)]
667pub struct SystemSyscallSignature {
668 params: Vec<ParamType>,
669 results: Vec<ValueType>,
670}
671
672impl SystemSyscallSignature {
673 pub fn new<const N: usize, const M: usize>(
674 params: [RegularParamType; N],
675 results: [ValueType; M],
676 ) -> Self {
677 SystemSyscallSignature {
678 params: params.into_iter().map(ParamType::Regular).collect(),
679 results: results.to_vec(),
680 }
681 }
682
683 pub fn params(&self) -> &[ParamType] {
684 &self.params
685 }
686
687 pub fn results(&self) -> &[ValueType] {
688 &self.results
689 }
690}
691
692impl<const N: usize, const M: usize> From<([RegularParamType; N], [ValueType; M])>
693 for SystemSyscallSignature
694{
695 fn from((params, results): ([RegularParamType; N], [ValueType; M])) -> Self {
696 SystemSyscallSignature::new(params, results)
697 }
698}
699
700mod pointers {
702 use super::{HashType, ParamType, RegularParamType};
703
704 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
706 pub enum Ptr {
707 SizedBufferStart { length_param_idx: usize },
709 Hash(HashType),
710 Value,
711 HashWithValue(HashType),
712 TwoHashes(HashType, HashType),
713 TwoHashesWithValue(HashType, HashType),
714 MutBlockNumber,
716 MutBlockTimestamp,
717 MutSizedBufferStart { length_param_idx: usize },
718 MutBufferStart,
719 MutHash(HashType),
720 MutGas,
721 MutLength,
722 MutValue,
723 MutBlockNumberWithHash(HashType),
724 }
725
726 impl Ptr {
727 pub fn is_mutable(self) -> bool {
728 use Ptr::*;
729
730 match self {
731 SizedBufferStart { .. }
732 | Hash(_)
733 | Value
734 | HashWithValue(_)
735 | TwoHashes(_, _)
736 | TwoHashesWithValue(_, _) => false,
737 MutBlockNumber
738 | MutBlockTimestamp
739 | MutSizedBufferStart { .. }
740 | MutBufferStart
741 | MutHash(_)
742 | MutGas
743 | MutLength
744 | MutValue
745 | MutBlockNumberWithHash(_) => true,
746 }
747 }
748 }
749
750 impl From<Ptr> for RegularParamType {
751 fn from(ptr: Ptr) -> RegularParamType {
752 RegularParamType::Pointer(ptr)
753 }
754 }
755
756 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
758 pub enum ErrPtr {
759 ErrorCode,
760 ErrorWithReplyCode,
761 ErrorWithSignalCode,
762 ErrorWithGas,
763 ErrorWithHandle,
764 ErrorWithHash(HashType),
765 ErrorWithTwoHashes(HashType, HashType),
766 }
767
768 impl From<ErrPtr> for ParamType {
769 fn from(err_ptr: ErrPtr) -> ParamType {
770 ParamType::Error(err_ptr)
771 }
772 }
773}