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