1#[doc(hidden)]
3static __BOXOLOGY_CONTRACT_DESCRIPTOR: ::std::sync::LazyLock<
4 ::boxology_contract::ContractDescriptor,
5> = ::std::sync::LazyLock::new(|| {
6 let box_id = ::boxology_contract::BoxId::new("check")
7 .expect("generated box identity is valid");
8 let error = ::boxology_contract::TypeDescriptor::enumeration([
9 ::boxology_contract::VariantDescriptor::new(
10 "Internal",
11 ::boxology_contract::VariantPayload::Unit,
12 None,
13 ),
14 ])
15 .expect("generated error descriptor is valid");
16 let capability = ::boxology_contract::CapabilityDescriptor::new(
17 ::boxology_contract::CapabilityId::new(
18 box_id.clone(),
19 ::boxology_contract::CapabilityName::new("check")
20 .expect("generated capability name is valid"),
21 ),
22 ::boxology_contract::TypeDescriptor::structure([
23 ::boxology_contract::FieldDescriptor::new(
24 "workspace",
25 ::boxology_contract::TypeDescriptor::string(),
26 None,
27 ),
28 ::boxology_contract::FieldDescriptor::new(
29 "base",
30 ::boxology_contract::TypeDescriptor::optional(
31 ::boxology_contract::TypeDescriptor::string(),
32 )
33 .expect("generated optional descriptor is valid"),
34 None,
35 ),
36 ])
37 .expect("generated struct descriptor is valid"),
38 ::boxology_contract::TypeDescriptor::structure([
39 ::boxology_contract::FieldDescriptor::new(
40 "report",
41 ::boxology_contract::TypeDescriptor::optional(
42 ::boxology_contract::TypeDescriptor::structure([
43 ::boxology_contract::FieldDescriptor::new(
44 "steps",
45 ::boxology_contract::TypeDescriptor::list(
46 ::boxology_contract::TypeDescriptor::structure([
47 ::boxology_contract::FieldDescriptor::new(
48 "id",
49 ::boxology_contract::TypeDescriptor::string(),
50 None,
51 ),
52 ::boxology_contract::FieldDescriptor::new(
53 "status",
54 ::boxology_contract::TypeDescriptor::enumeration([
55 ::boxology_contract::VariantDescriptor::new(
56 "Passed",
57 ::boxology_contract::VariantPayload::Unit,
58 None,
59 ),
60 ::boxology_contract::VariantDescriptor::new(
61 "Failed",
62 ::boxology_contract::VariantPayload::Unit,
63 None,
64 ),
65 ::boxology_contract::VariantDescriptor::new(
66 "Skipped",
67 ::boxology_contract::VariantPayload::Unit,
68 None,
69 ),
70 ])
71 .expect("generated enum descriptor is valid"),
72 None,
73 ),
74 ::boxology_contract::FieldDescriptor::new(
75 "reason",
76 ::boxology_contract::TypeDescriptor::optional(
77 ::boxology_contract::TypeDescriptor::string(),
78 )
79 .expect("generated optional descriptor is valid"),
80 None,
81 ),
82 ::boxology_contract::FieldDescriptor::new(
83 "findings",
84 ::boxology_contract::TypeDescriptor::list(
85 ::boxology_contract::TypeDescriptor::structure([
86 ::boxology_contract::FieldDescriptor::new(
87 "kind",
88 ::boxology_contract::TypeDescriptor::string(),
89 None,
90 ),
91 ::boxology_contract::FieldDescriptor::new(
92 "code",
93 ::boxology_contract::TypeDescriptor::string(),
94 None,
95 ),
96 ::boxology_contract::FieldDescriptor::new(
97 "path",
98 ::boxology_contract::TypeDescriptor::string(),
99 None,
100 ),
101 ::boxology_contract::FieldDescriptor::new(
102 "package",
103 ::boxology_contract::TypeDescriptor::optional(
104 ::boxology_contract::TypeDescriptor::string(),
105 )
106 .expect("generated optional descriptor is valid"),
107 None,
108 ),
109 ::boxology_contract::FieldDescriptor::new(
110 "payload",
111 ::boxology_contract::TypeDescriptor::optional(
112 ::boxology_contract::TypeDescriptor::string(),
113 )
114 .expect("generated optional descriptor is valid"),
115 None,
116 ),
117 ::boxology_contract::FieldDescriptor::new(
118 "rule",
119 ::boxology_contract::TypeDescriptor::optional(
120 ::boxology_contract::TypeDescriptor::string(),
121 )
122 .expect("generated optional descriptor is valid"),
123 None,
124 ),
125 ::boxology_contract::FieldDescriptor::new(
126 "rule_source",
127 ::boxology_contract::TypeDescriptor::optional(
128 ::boxology_contract::TypeDescriptor::string(),
129 )
130 .expect("generated optional descriptor is valid"),
131 None,
132 ),
133 ::boxology_contract::FieldDescriptor::new(
134 "span_start_line",
135 ::boxology_contract::TypeDescriptor::optional(
136 ::boxology_contract::TypeDescriptor::u64(),
137 )
138 .expect("generated optional descriptor is valid"),
139 None,
140 ),
141 ::boxology_contract::FieldDescriptor::new(
142 "span_start_column",
143 ::boxology_contract::TypeDescriptor::optional(
144 ::boxology_contract::TypeDescriptor::u64(),
145 )
146 .expect("generated optional descriptor is valid"),
147 None,
148 ),
149 ::boxology_contract::FieldDescriptor::new(
150 "span_end_line",
151 ::boxology_contract::TypeDescriptor::optional(
152 ::boxology_contract::TypeDescriptor::u64(),
153 )
154 .expect("generated optional descriptor is valid"),
155 None,
156 ),
157 ::boxology_contract::FieldDescriptor::new(
158 "span_end_column",
159 ::boxology_contract::TypeDescriptor::optional(
160 ::boxology_contract::TypeDescriptor::u64(),
161 )
162 .expect("generated optional descriptor is valid"),
163 None,
164 ),
165 ::boxology_contract::FieldDescriptor::new(
166 "offending",
167 ::boxology_contract::TypeDescriptor::optional(
168 ::boxology_contract::TypeDescriptor::string(),
169 )
170 .expect("generated optional descriptor is valid"),
171 None,
172 ),
173 ::boxology_contract::FieldDescriptor::new(
174 "class",
175 ::boxology_contract::TypeDescriptor::optional(
176 ::boxology_contract::TypeDescriptor::string(),
177 )
178 .expect("generated optional descriptor is valid"),
179 None,
180 ),
181 ::boxology_contract::FieldDescriptor::new(
182 "condition",
183 ::boxology_contract::TypeDescriptor::optional(
184 ::boxology_contract::TypeDescriptor::string(),
185 )
186 .expect("generated optional descriptor is valid"),
187 None,
188 ),
189 ])
190 .expect("generated struct descriptor is valid"),
191 )
192 .expect("generated list descriptor is valid"),
193 None,
194 ),
195 ::boxology_contract::FieldDescriptor::new(
196 "output",
197 ::boxology_contract::TypeDescriptor::optional(
198 ::boxology_contract::TypeDescriptor::list(
199 ::boxology_contract::TypeDescriptor::u8(),
200 )
201 .expect("generated list descriptor is valid"),
202 )
203 .expect("generated optional descriptor is valid"),
204 None,
205 ),
206 ])
207 .expect("generated struct descriptor is valid"),
208 )
209 .expect("generated list descriptor is valid"),
210 None,
211 ),
212 ::boxology_contract::FieldDescriptor::new(
213 "status",
214 ::boxology_contract::TypeDescriptor::enumeration([
215 ::boxology_contract::VariantDescriptor::new(
216 "Passed",
217 ::boxology_contract::VariantPayload::Unit,
218 None,
219 ),
220 ::boxology_contract::VariantDescriptor::new(
221 "Failed",
222 ::boxology_contract::VariantPayload::Unit,
223 None,
224 ),
225 ])
226 .expect("generated enum descriptor is valid"),
227 None,
228 ),
229 ::boxology_contract::FieldDescriptor::new(
230 "human",
231 ::boxology_contract::TypeDescriptor::list(
232 ::boxology_contract::TypeDescriptor::u8(),
233 )
234 .expect("generated list descriptor is valid"),
235 None,
236 ),
237 ::boxology_contract::FieldDescriptor::new(
238 "json",
239 ::boxology_contract::TypeDescriptor::list(
240 ::boxology_contract::TypeDescriptor::u8(),
241 )
242 .expect("generated list descriptor is valid"),
243 None,
244 ),
245 ])
246 .expect("generated struct descriptor is valid"),
247 )
248 .expect("generated optional descriptor is valid"),
249 None,
250 ),
251 ::boxology_contract::FieldDescriptor::new(
252 "failure",
253 ::boxology_contract::TypeDescriptor::optional(
254 ::boxology_contract::TypeDescriptor::structure([
255 ::boxology_contract::FieldDescriptor::new(
256 "kind",
257 ::boxology_contract::TypeDescriptor::enumeration([
258 ::boxology_contract::VariantDescriptor::new(
259 "Validation",
260 ::boxology_contract::VariantPayload::Unit,
261 None,
262 ),
263 ::boxology_contract::VariantDescriptor::new(
264 "Invocation",
265 ::boxology_contract::VariantPayload::Unit,
266 None,
267 ),
268 ])
269 .expect("generated enum descriptor is valid"),
270 None,
271 ),
272 ::boxology_contract::FieldDescriptor::new(
273 "human",
274 ::boxology_contract::TypeDescriptor::list(
275 ::boxology_contract::TypeDescriptor::u8(),
276 )
277 .expect("generated list descriptor is valid"),
278 None,
279 ),
280 ::boxology_contract::FieldDescriptor::new(
281 "json",
282 ::boxology_contract::TypeDescriptor::list(
283 ::boxology_contract::TypeDescriptor::u8(),
284 )
285 .expect("generated list descriptor is valid"),
286 None,
287 ),
288 ])
289 .expect("generated struct descriptor is valid"),
290 )
291 .expect("generated optional descriptor is valid"),
292 None,
293 ),
294 ])
295 .expect("generated struct descriptor is valid"),
296 error,
297 ::boxology_contract::CapabilityShape::Unary,
298 ::boxology_contract::ExposureLevel::CodeOnly,
299 ::boxology_contract::Idempotency::None,
300 None,
301 );
302 ::boxology_contract::ContractDescriptor::new(
303 box_id,
304 [capability],
305 ::boxology_contract::ContractRevision::new(
306 "sha256:3990c9cd7afa80360c2051526516fafd71ab94890bf27f6aa4e057669f99754d",
307 )
308 .expect("generated contract revision is non-empty"),
309 )
310 .expect("generated contract descriptor is valid")
311});
312pub fn contract_descriptor() -> &'static ::boxology_contract::ContractDescriptor {
314 &__BOXOLOGY_CONTRACT_DESCRIPTOR
315}
316use std::future::Future;
317use std::pin::Pin;
318use std::sync::{Arc, LazyLock};
319use ::boxology_contract::{
320 BoxId, CallContext, CallError, CapabilityId, CapabilityName, ContractType,
321 DecodeRole, Detail, ErasedCallTarget, TypeDescriptor,
322};
323pub trait CheckDispatch: Send + Sync + 'static {
324 fn check<'a>(
325 &'a self,
326 context: CallContext,
327 request: CheckRequest,
328 ) -> Pin<Box<dyn Future<Output = Result<CheckOutcome, CheckError>> + Send + 'a>>;
329}
330#[derive(Clone)]
331pub struct CheckHandle {
332 target: Arc<dyn ErasedCallTarget>,
333}
334impl CheckHandle {
335 #[doc(hidden)]
336 pub fn from_erased(target: Arc<dyn ErasedCallTarget>) -> Self {
337 Self { target }
338 }
339 pub async fn check(
340 &self,
341 context: CallContext,
342 request: CheckRequest,
343 ) -> Result<CheckOutcome, CallError<CheckError>> {
344 let input = request
345 .encode()
346 .map_err(|error| conversion_detail("input_encode", error))
347 .map_err(CallError::ContractViolation)?;
348 let output = self
349 .target
350 .call(&CHECK_CHECK, context, input)
351 .await
352 .map_err(|error| error.into_typed::<CheckError>(&CHECK_ERROR_DESCRIPTOR))?;
353 let output = TypeDescriptor::structure([
354 ::boxology_contract::FieldDescriptor::new(
355 "report",
356 TypeDescriptor::optional(
357 TypeDescriptor::structure([
358 ::boxology_contract::FieldDescriptor::new(
359 "steps",
360 TypeDescriptor::list(
361 TypeDescriptor::structure([
362 ::boxology_contract::FieldDescriptor::new(
363 "id",
364 TypeDescriptor::string(),
365 None,
366 ),
367 ::boxology_contract::FieldDescriptor::new(
368 "status",
369 TypeDescriptor::enumeration([
370 ::boxology_contract::VariantDescriptor::new(
371 "Passed",
372 ::boxology_contract::VariantPayload::Unit,
373 None,
374 ),
375 ::boxology_contract::VariantDescriptor::new(
376 "Failed",
377 ::boxology_contract::VariantPayload::Unit,
378 None,
379 ),
380 ::boxology_contract::VariantDescriptor::new(
381 "Skipped",
382 ::boxology_contract::VariantPayload::Unit,
383 None,
384 ),
385 ])
386 .expect("generated enum descriptor is valid"),
387 None,
388 ),
389 ::boxology_contract::FieldDescriptor::new(
390 "reason",
391 TypeDescriptor::optional(TypeDescriptor::string())
392 .expect("generated optional descriptor is valid"),
393 None,
394 ),
395 ::boxology_contract::FieldDescriptor::new(
396 "findings",
397 TypeDescriptor::list(
398 TypeDescriptor::structure([
399 ::boxology_contract::FieldDescriptor::new(
400 "kind",
401 TypeDescriptor::string(),
402 None,
403 ),
404 ::boxology_contract::FieldDescriptor::new(
405 "code",
406 TypeDescriptor::string(),
407 None,
408 ),
409 ::boxology_contract::FieldDescriptor::new(
410 "path",
411 TypeDescriptor::string(),
412 None,
413 ),
414 ::boxology_contract::FieldDescriptor::new(
415 "package",
416 TypeDescriptor::optional(TypeDescriptor::string())
417 .expect("generated optional descriptor is valid"),
418 None,
419 ),
420 ::boxology_contract::FieldDescriptor::new(
421 "payload",
422 TypeDescriptor::optional(TypeDescriptor::string())
423 .expect("generated optional descriptor is valid"),
424 None,
425 ),
426 ::boxology_contract::FieldDescriptor::new(
427 "rule",
428 TypeDescriptor::optional(TypeDescriptor::string())
429 .expect("generated optional descriptor is valid"),
430 None,
431 ),
432 ::boxology_contract::FieldDescriptor::new(
433 "rule_source",
434 TypeDescriptor::optional(TypeDescriptor::string())
435 .expect("generated optional descriptor is valid"),
436 None,
437 ),
438 ::boxology_contract::FieldDescriptor::new(
439 "span_start_line",
440 TypeDescriptor::optional(TypeDescriptor::u64())
441 .expect("generated optional descriptor is valid"),
442 None,
443 ),
444 ::boxology_contract::FieldDescriptor::new(
445 "span_start_column",
446 TypeDescriptor::optional(TypeDescriptor::u64())
447 .expect("generated optional descriptor is valid"),
448 None,
449 ),
450 ::boxology_contract::FieldDescriptor::new(
451 "span_end_line",
452 TypeDescriptor::optional(TypeDescriptor::u64())
453 .expect("generated optional descriptor is valid"),
454 None,
455 ),
456 ::boxology_contract::FieldDescriptor::new(
457 "span_end_column",
458 TypeDescriptor::optional(TypeDescriptor::u64())
459 .expect("generated optional descriptor is valid"),
460 None,
461 ),
462 ::boxology_contract::FieldDescriptor::new(
463 "offending",
464 TypeDescriptor::optional(TypeDescriptor::string())
465 .expect("generated optional descriptor is valid"),
466 None,
467 ),
468 ::boxology_contract::FieldDescriptor::new(
469 "class",
470 TypeDescriptor::optional(TypeDescriptor::string())
471 .expect("generated optional descriptor is valid"),
472 None,
473 ),
474 ::boxology_contract::FieldDescriptor::new(
475 "condition",
476 TypeDescriptor::optional(TypeDescriptor::string())
477 .expect("generated optional descriptor is valid"),
478 None,
479 ),
480 ])
481 .expect("generated struct descriptor is valid"),
482 )
483 .expect("generated list descriptor is valid"),
484 None,
485 ),
486 ::boxology_contract::FieldDescriptor::new(
487 "output",
488 TypeDescriptor::optional(
489 TypeDescriptor::list(TypeDescriptor::u8())
490 .expect("generated list descriptor is valid"),
491 )
492 .expect("generated optional descriptor is valid"),
493 None,
494 ),
495 ])
496 .expect("generated struct descriptor is valid"),
497 )
498 .expect("generated list descriptor is valid"),
499 None,
500 ),
501 ::boxology_contract::FieldDescriptor::new(
502 "status",
503 TypeDescriptor::enumeration([
504 ::boxology_contract::VariantDescriptor::new(
505 "Passed",
506 ::boxology_contract::VariantPayload::Unit,
507 None,
508 ),
509 ::boxology_contract::VariantDescriptor::new(
510 "Failed",
511 ::boxology_contract::VariantPayload::Unit,
512 None,
513 ),
514 ])
515 .expect("generated enum descriptor is valid"),
516 None,
517 ),
518 ::boxology_contract::FieldDescriptor::new(
519 "human",
520 TypeDescriptor::list(TypeDescriptor::u8())
521 .expect("generated list descriptor is valid"),
522 None,
523 ),
524 ::boxology_contract::FieldDescriptor::new(
525 "json",
526 TypeDescriptor::list(TypeDescriptor::u8())
527 .expect("generated list descriptor is valid"),
528 None,
529 ),
530 ])
531 .expect("generated struct descriptor is valid"),
532 )
533 .expect("generated optional descriptor is valid"),
534 None,
535 ),
536 ::boxology_contract::FieldDescriptor::new(
537 "failure",
538 TypeDescriptor::optional(
539 TypeDescriptor::structure([
540 ::boxology_contract::FieldDescriptor::new(
541 "kind",
542 TypeDescriptor::enumeration([
543 ::boxology_contract::VariantDescriptor::new(
544 "Validation",
545 ::boxology_contract::VariantPayload::Unit,
546 None,
547 ),
548 ::boxology_contract::VariantDescriptor::new(
549 "Invocation",
550 ::boxology_contract::VariantPayload::Unit,
551 None,
552 ),
553 ])
554 .expect("generated enum descriptor is valid"),
555 None,
556 ),
557 ::boxology_contract::FieldDescriptor::new(
558 "human",
559 TypeDescriptor::list(TypeDescriptor::u8())
560 .expect("generated list descriptor is valid"),
561 None,
562 ),
563 ::boxology_contract::FieldDescriptor::new(
564 "json",
565 TypeDescriptor::list(TypeDescriptor::u8())
566 .expect("generated list descriptor is valid"),
567 None,
568 ),
569 ])
570 .expect("generated struct descriptor is valid"),
571 )
572 .expect("generated optional descriptor is valid"),
573 None,
574 ),
575 ])
576 .expect("generated struct descriptor is valid")
577 .conform(DecodeRole::ConsumerOutput, output)
578 .map_err(|error| conversion_detail("output_decode", error))
579 .map_err(CallError::InvalidResponse)?;
580 <CheckOutcome as ContractType>::decode(&output)
581 .map_err(|error| conversion_detail("output_decode", error))
582 .map_err(CallError::InvalidResponse)
583 }
584}
585impl ::boxology_contract::BoxHandle for CheckHandle {
586 fn from_erased(target: Arc<dyn ErasedCallTarget>) -> Self {
587 Self::from_erased(target)
588 }
589}
590static CHECK_CHECK: LazyLock<CapabilityId> = LazyLock::new(|| {
591 CapabilityId::new(
592 BoxId::new("check").expect("generated box identity is valid"),
593 CapabilityName::new("check").expect("generated capability name is valid"),
594 )
595});
596static CHECK_ERROR_DESCRIPTOR: LazyLock<TypeDescriptor> = LazyLock::new(|| {
597 TypeDescriptor::enumeration([
598 ::boxology_contract::VariantDescriptor::new(
599 "Internal",
600 ::boxology_contract::VariantPayload::Unit,
601 None,
602 ),
603 ])
604 .expect("generated check error descriptor is valid")
605});
606fn conversion_detail(code: &'static str, error: impl std::fmt::Display) -> Detail {
607 Detail::new(code).with_message(error.to_string())
608}
609#[derive(Debug, Clone, PartialEq)]
610pub struct CheckRequest {
611 pub workspace: ::std::string::String,
612 pub base: ::core::option::Option<::std::string::String>,
613}
614impl ::boxology_contract::ContractType for CheckRequest {
615 fn encode_value(
616 &self,
617 ) -> ::core::result::Result<
618 ::boxology_contract::ContractValue,
619 ::boxology_contract::EncodeError,
620 > {
621 let mut fields = ::std::vec::Vec::new();
622 if let Some(value) = ::boxology_contract::ContractType::encode_field(
623 &self.workspace,
624 )
625 .map_err(|error| {
626 error.under(::boxology_contract::PathSegment::Field("workspace".into()))
627 })?
628 {
629 fields.push(("workspace".into(), value));
630 }
631 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.base)
632 .map_err(|error| {
633 error.under(::boxology_contract::PathSegment::Field("base".into()))
634 })?
635 {
636 fields.push(("base".into(), value));
637 }
638 ::boxology_contract::ContractValue::object(fields)
639 .map_err(|_| unreachable!("validated generated field identities are unique"))
640 }
641 fn decode_value(
642 value: &::boxology_contract::ContractValue,
643 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
644 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
645 return Err(
646 ::boxology_contract::DecodeError::new(
647 ::boxology_contract::DecodeErrorKind::KindMismatch,
648 ),
649 );
650 };
651 for (field, _) in fields.entries() {
652 match field {
653 "workspace" | "base" => {}
654 _ => {
655 return Err(
656 ::boxology_contract::DecodeError::new(
657 ::boxology_contract::DecodeErrorKind::UnknownField(
658 field.into(),
659 ),
660 )
661 .under(::boxology_contract::PathSegment::Field(field.into())),
662 );
663 }
664 }
665 }
666 Ok(Self {
667 workspace: <::std::string::String as ::boxology_contract::ContractType>::decode_field(
668 fields.get("workspace"),
669 )
670 .map_err(|error| {
671 error
672 .under(
673 ::boxology_contract::PathSegment::Field("workspace".into()),
674 )
675 })?,
676 base: <::core::option::Option<
677 ::std::string::String,
678 > as ::boxology_contract::ContractType>::decode_field(fields.get("base"))
679 .map_err(|error| {
680 error.under(::boxology_contract::PathSegment::Field("base".into()))
681 })?,
682 })
683 }
684}
685#[derive(Debug, Clone, PartialEq)]
686pub enum CheckStatus {
687 Passed,
688 Failed,
689 Unknown { tag: ::std::string::String, payload: ::boxology_contract::OpaquePayload },
690}
691impl ::boxology_contract::ContractType for CheckStatus {
692 fn encode_value(
693 &self,
694 ) -> ::core::result::Result<
695 ::boxology_contract::ContractValue,
696 ::boxology_contract::EncodeError,
697 > {
698 let (tag, payload) = match self {
699 Self::Passed => ("Passed".into(), ::boxology_contract::SlotValue::Null),
700 Self::Failed => ("Failed".into(), ::boxology_contract::SlotValue::Null),
701 Self::Unknown { tag, payload } => {
702 (
703 tag.clone(),
704 ::boxology_contract::SlotValue::Value(
705 ::boxology_contract::ContractValue::opaque(payload.forward()),
706 ),
707 )
708 }
709 };
710 Ok(::boxology_contract::ContractValue::enum_value(tag, payload))
711 }
712 fn decode_value(
713 value: &::boxology_contract::ContractValue,
714 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
715 let ::boxology_contract::ValueRef::Enum { tag, payload } = value.view() else {
716 return Err(
717 ::boxology_contract::DecodeError::new(
718 ::boxology_contract::DecodeErrorKind::KindMismatch,
719 ),
720 );
721 };
722 match tag {
723 "Passed" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
724 Ok(Self::Passed)
725 }
726 "Passed" => {
727 Err(
728 ::boxology_contract::DecodeError::new(
729 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
730 )
731 .under(::boxology_contract::PathSegment::Variant(tag.into())),
732 )
733 }
734 "Failed" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
735 Ok(Self::Failed)
736 }
737 "Failed" => {
738 Err(
739 ::boxology_contract::DecodeError::new(
740 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
741 )
742 .under(::boxology_contract::PathSegment::Variant(tag.into())),
743 )
744 }
745 _ => {
746 match payload {
747 ::boxology_contract::SlotValue::Value(value) => {
748 match value.view() {
749 ::boxology_contract::ValueRef::Opaque(payload) => {
750 Ok(Self::Unknown {
751 tag: tag.into(),
752 payload: payload.forward(),
753 })
754 }
755 _ => {
756 Err(
757 ::boxology_contract::DecodeError::new(
758 ::boxology_contract::DecodeErrorKind::UnknownVariant(
759 tag.into(),
760 ),
761 )
762 .under(
763 ::boxology_contract::PathSegment::Variant(tag.into()),
764 ),
765 )
766 }
767 }
768 }
769 _ => {
770 Err(
771 ::boxology_contract::DecodeError::new(
772 ::boxology_contract::DecodeErrorKind::UnknownVariant(
773 tag.into(),
774 ),
775 )
776 .under(
777 ::boxology_contract::PathSegment::Variant(tag.into()),
778 ),
779 )
780 }
781 }
782 }
783 }
784 }
785}
786#[derive(Debug, Clone, PartialEq)]
787pub enum CheckStepStatus {
788 Passed,
789 Failed,
790 Skipped,
791 Unknown { tag: ::std::string::String, payload: ::boxology_contract::OpaquePayload },
792}
793impl ::boxology_contract::ContractType for CheckStepStatus {
794 fn encode_value(
795 &self,
796 ) -> ::core::result::Result<
797 ::boxology_contract::ContractValue,
798 ::boxology_contract::EncodeError,
799 > {
800 let (tag, payload) = match self {
801 Self::Passed => ("Passed".into(), ::boxology_contract::SlotValue::Null),
802 Self::Failed => ("Failed".into(), ::boxology_contract::SlotValue::Null),
803 Self::Skipped => ("Skipped".into(), ::boxology_contract::SlotValue::Null),
804 Self::Unknown { tag, payload } => {
805 (
806 tag.clone(),
807 ::boxology_contract::SlotValue::Value(
808 ::boxology_contract::ContractValue::opaque(payload.forward()),
809 ),
810 )
811 }
812 };
813 Ok(::boxology_contract::ContractValue::enum_value(tag, payload))
814 }
815 fn decode_value(
816 value: &::boxology_contract::ContractValue,
817 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
818 let ::boxology_contract::ValueRef::Enum { tag, payload } = value.view() else {
819 return Err(
820 ::boxology_contract::DecodeError::new(
821 ::boxology_contract::DecodeErrorKind::KindMismatch,
822 ),
823 );
824 };
825 match tag {
826 "Passed" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
827 Ok(Self::Passed)
828 }
829 "Passed" => {
830 Err(
831 ::boxology_contract::DecodeError::new(
832 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
833 )
834 .under(::boxology_contract::PathSegment::Variant(tag.into())),
835 )
836 }
837 "Failed" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
838 Ok(Self::Failed)
839 }
840 "Failed" => {
841 Err(
842 ::boxology_contract::DecodeError::new(
843 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
844 )
845 .under(::boxology_contract::PathSegment::Variant(tag.into())),
846 )
847 }
848 "Skipped" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
849 Ok(Self::Skipped)
850 }
851 "Skipped" => {
852 Err(
853 ::boxology_contract::DecodeError::new(
854 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
855 )
856 .under(::boxology_contract::PathSegment::Variant(tag.into())),
857 )
858 }
859 _ => {
860 match payload {
861 ::boxology_contract::SlotValue::Value(value) => {
862 match value.view() {
863 ::boxology_contract::ValueRef::Opaque(payload) => {
864 Ok(Self::Unknown {
865 tag: tag.into(),
866 payload: payload.forward(),
867 })
868 }
869 _ => {
870 Err(
871 ::boxology_contract::DecodeError::new(
872 ::boxology_contract::DecodeErrorKind::UnknownVariant(
873 tag.into(),
874 ),
875 )
876 .under(
877 ::boxology_contract::PathSegment::Variant(tag.into()),
878 ),
879 )
880 }
881 }
882 }
883 _ => {
884 Err(
885 ::boxology_contract::DecodeError::new(
886 ::boxology_contract::DecodeErrorKind::UnknownVariant(
887 tag.into(),
888 ),
889 )
890 .under(
891 ::boxology_contract::PathSegment::Variant(tag.into()),
892 ),
893 )
894 }
895 }
896 }
897 }
898 }
899}
900#[derive(Debug, Clone, PartialEq)]
901pub enum CheckFailureKind {
902 Validation,
903 Invocation,
904 Unknown { tag: ::std::string::String, payload: ::boxology_contract::OpaquePayload },
905}
906impl ::boxology_contract::ContractType for CheckFailureKind {
907 fn encode_value(
908 &self,
909 ) -> ::core::result::Result<
910 ::boxology_contract::ContractValue,
911 ::boxology_contract::EncodeError,
912 > {
913 let (tag, payload) = match self {
914 Self::Validation => {
915 ("Validation".into(), ::boxology_contract::SlotValue::Null)
916 }
917 Self::Invocation => {
918 ("Invocation".into(), ::boxology_contract::SlotValue::Null)
919 }
920 Self::Unknown { tag, payload } => {
921 (
922 tag.clone(),
923 ::boxology_contract::SlotValue::Value(
924 ::boxology_contract::ContractValue::opaque(payload.forward()),
925 ),
926 )
927 }
928 };
929 Ok(::boxology_contract::ContractValue::enum_value(tag, payload))
930 }
931 fn decode_value(
932 value: &::boxology_contract::ContractValue,
933 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
934 let ::boxology_contract::ValueRef::Enum { tag, payload } = value.view() else {
935 return Err(
936 ::boxology_contract::DecodeError::new(
937 ::boxology_contract::DecodeErrorKind::KindMismatch,
938 ),
939 );
940 };
941 match tag {
942 "Validation" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
943 Ok(Self::Validation)
944 }
945 "Validation" => {
946 Err(
947 ::boxology_contract::DecodeError::new(
948 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
949 )
950 .under(::boxology_contract::PathSegment::Variant(tag.into())),
951 )
952 }
953 "Invocation" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
954 Ok(Self::Invocation)
955 }
956 "Invocation" => {
957 Err(
958 ::boxology_contract::DecodeError::new(
959 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
960 )
961 .under(::boxology_contract::PathSegment::Variant(tag.into())),
962 )
963 }
964 _ => {
965 match payload {
966 ::boxology_contract::SlotValue::Value(value) => {
967 match value.view() {
968 ::boxology_contract::ValueRef::Opaque(payload) => {
969 Ok(Self::Unknown {
970 tag: tag.into(),
971 payload: payload.forward(),
972 })
973 }
974 _ => {
975 Err(
976 ::boxology_contract::DecodeError::new(
977 ::boxology_contract::DecodeErrorKind::UnknownVariant(
978 tag.into(),
979 ),
980 )
981 .under(
982 ::boxology_contract::PathSegment::Variant(tag.into()),
983 ),
984 )
985 }
986 }
987 }
988 _ => {
989 Err(
990 ::boxology_contract::DecodeError::new(
991 ::boxology_contract::DecodeErrorKind::UnknownVariant(
992 tag.into(),
993 ),
994 )
995 .under(
996 ::boxology_contract::PathSegment::Variant(tag.into()),
997 ),
998 )
999 }
1000 }
1001 }
1002 }
1003 }
1004}
1005#[derive(Debug, Clone, PartialEq)]
1006pub struct CheckFinding {
1007 pub kind: ::std::string::String,
1008 pub code: ::std::string::String,
1009 pub path: ::std::string::String,
1010 pub package: ::core::option::Option<::std::string::String>,
1011 pub payload: ::core::option::Option<::std::string::String>,
1012 pub rule: ::core::option::Option<::std::string::String>,
1013 pub rule_source: ::core::option::Option<::std::string::String>,
1014 pub span_start_line: ::core::option::Option<u64>,
1015 pub span_start_column: ::core::option::Option<u64>,
1016 pub span_end_line: ::core::option::Option<u64>,
1017 pub span_end_column: ::core::option::Option<u64>,
1018 pub offending: ::core::option::Option<::std::string::String>,
1019 pub class: ::core::option::Option<::std::string::String>,
1020 pub condition: ::core::option::Option<::std::string::String>,
1021}
1022impl ::boxology_contract::ContractType for CheckFinding {
1023 fn encode_value(
1024 &self,
1025 ) -> ::core::result::Result<
1026 ::boxology_contract::ContractValue,
1027 ::boxology_contract::EncodeError,
1028 > {
1029 let mut fields = ::std::vec::Vec::new();
1030 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.kind)
1031 .map_err(|error| {
1032 error.under(::boxology_contract::PathSegment::Field("kind".into()))
1033 })?
1034 {
1035 fields.push(("kind".into(), value));
1036 }
1037 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.code)
1038 .map_err(|error| {
1039 error.under(::boxology_contract::PathSegment::Field("code".into()))
1040 })?
1041 {
1042 fields.push(("code".into(), value));
1043 }
1044 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.path)
1045 .map_err(|error| {
1046 error.under(::boxology_contract::PathSegment::Field("path".into()))
1047 })?
1048 {
1049 fields.push(("path".into(), value));
1050 }
1051 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1052 &self.package,
1053 )
1054 .map_err(|error| {
1055 error.under(::boxology_contract::PathSegment::Field("package".into()))
1056 })?
1057 {
1058 fields.push(("package".into(), value));
1059 }
1060 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1061 &self.payload,
1062 )
1063 .map_err(|error| {
1064 error.under(::boxology_contract::PathSegment::Field("payload".into()))
1065 })?
1066 {
1067 fields.push(("payload".into(), value));
1068 }
1069 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.rule)
1070 .map_err(|error| {
1071 error.under(::boxology_contract::PathSegment::Field("rule".into()))
1072 })?
1073 {
1074 fields.push(("rule".into(), value));
1075 }
1076 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1077 &self.rule_source,
1078 )
1079 .map_err(|error| {
1080 error
1081 .under(::boxology_contract::PathSegment::Field("rule_source".into()))
1082 })?
1083 {
1084 fields.push(("rule_source".into(), value));
1085 }
1086 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1087 &self.span_start_line,
1088 )
1089 .map_err(|error| {
1090 error
1091 .under(
1092 ::boxology_contract::PathSegment::Field("span_start_line".into()),
1093 )
1094 })?
1095 {
1096 fields.push(("span_start_line".into(), value));
1097 }
1098 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1099 &self.span_start_column,
1100 )
1101 .map_err(|error| {
1102 error
1103 .under(
1104 ::boxology_contract::PathSegment::Field(
1105 "span_start_column".into(),
1106 ),
1107 )
1108 })?
1109 {
1110 fields.push(("span_start_column".into(), value));
1111 }
1112 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1113 &self.span_end_line,
1114 )
1115 .map_err(|error| {
1116 error
1117 .under(
1118 ::boxology_contract::PathSegment::Field("span_end_line".into()),
1119 )
1120 })?
1121 {
1122 fields.push(("span_end_line".into(), value));
1123 }
1124 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1125 &self.span_end_column,
1126 )
1127 .map_err(|error| {
1128 error
1129 .under(
1130 ::boxology_contract::PathSegment::Field("span_end_column".into()),
1131 )
1132 })?
1133 {
1134 fields.push(("span_end_column".into(), value));
1135 }
1136 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1137 &self.offending,
1138 )
1139 .map_err(|error| {
1140 error.under(::boxology_contract::PathSegment::Field("offending".into()))
1141 })?
1142 {
1143 fields.push(("offending".into(), value));
1144 }
1145 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.class)
1146 .map_err(|error| {
1147 error.under(::boxology_contract::PathSegment::Field("class".into()))
1148 })?
1149 {
1150 fields.push(("class".into(), value));
1151 }
1152 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1153 &self.condition,
1154 )
1155 .map_err(|error| {
1156 error.under(::boxology_contract::PathSegment::Field("condition".into()))
1157 })?
1158 {
1159 fields.push(("condition".into(), value));
1160 }
1161 ::boxology_contract::ContractValue::object(fields)
1162 .map_err(|_| unreachable!("validated generated field identities are unique"))
1163 }
1164 fn decode_value(
1165 value: &::boxology_contract::ContractValue,
1166 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1167 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
1168 return Err(
1169 ::boxology_contract::DecodeError::new(
1170 ::boxology_contract::DecodeErrorKind::KindMismatch,
1171 ),
1172 );
1173 };
1174 for (field, _) in fields.entries() {
1175 match field {
1176 "kind" | "code" | "path" | "package" | "payload" | "rule" | "rule_source"
1177 | "span_start_line" | "span_start_column" | "span_end_line"
1178 | "span_end_column" | "offending" | "class" | "condition" => {}
1179 _ => {
1180 return Err(
1181 ::boxology_contract::DecodeError::new(
1182 ::boxology_contract::DecodeErrorKind::UnknownField(
1183 field.into(),
1184 ),
1185 )
1186 .under(::boxology_contract::PathSegment::Field(field.into())),
1187 );
1188 }
1189 }
1190 }
1191 Ok(Self {
1192 kind: <::std::string::String as ::boxology_contract::ContractType>::decode_field(
1193 fields.get("kind"),
1194 )
1195 .map_err(|error| {
1196 error.under(::boxology_contract::PathSegment::Field("kind".into()))
1197 })?,
1198 code: <::std::string::String as ::boxology_contract::ContractType>::decode_field(
1199 fields.get("code"),
1200 )
1201 .map_err(|error| {
1202 error.under(::boxology_contract::PathSegment::Field("code".into()))
1203 })?,
1204 path: <::std::string::String as ::boxology_contract::ContractType>::decode_field(
1205 fields.get("path"),
1206 )
1207 .map_err(|error| {
1208 error.under(::boxology_contract::PathSegment::Field("path".into()))
1209 })?,
1210 package: <::core::option::Option<
1211 ::std::string::String,
1212 > as ::boxology_contract::ContractType>::decode_field(fields.get("package"))
1213 .map_err(|error| {
1214 error
1215 .under(::boxology_contract::PathSegment::Field("package".into()))
1216 })?,
1217 payload: <::core::option::Option<
1218 ::std::string::String,
1219 > as ::boxology_contract::ContractType>::decode_field(fields.get("payload"))
1220 .map_err(|error| {
1221 error
1222 .under(::boxology_contract::PathSegment::Field("payload".into()))
1223 })?,
1224 rule: <::core::option::Option<
1225 ::std::string::String,
1226 > as ::boxology_contract::ContractType>::decode_field(fields.get("rule"))
1227 .map_err(|error| {
1228 error.under(::boxology_contract::PathSegment::Field("rule".into()))
1229 })?,
1230 rule_source: <::core::option::Option<
1231 ::std::string::String,
1232 > as ::boxology_contract::ContractType>::decode_field(
1233 fields.get("rule_source"),
1234 )
1235 .map_err(|error| {
1236 error
1237 .under(
1238 ::boxology_contract::PathSegment::Field("rule_source".into()),
1239 )
1240 })?,
1241 span_start_line: <::core::option::Option<
1242 u64,
1243 > as ::boxology_contract::ContractType>::decode_field(
1244 fields.get("span_start_line"),
1245 )
1246 .map_err(|error| {
1247 error
1248 .under(
1249 ::boxology_contract::PathSegment::Field(
1250 "span_start_line".into(),
1251 ),
1252 )
1253 })?,
1254 span_start_column: <::core::option::Option<
1255 u64,
1256 > as ::boxology_contract::ContractType>::decode_field(
1257 fields.get("span_start_column"),
1258 )
1259 .map_err(|error| {
1260 error
1261 .under(
1262 ::boxology_contract::PathSegment::Field(
1263 "span_start_column".into(),
1264 ),
1265 )
1266 })?,
1267 span_end_line: <::core::option::Option<
1268 u64,
1269 > as ::boxology_contract::ContractType>::decode_field(
1270 fields.get("span_end_line"),
1271 )
1272 .map_err(|error| {
1273 error
1274 .under(
1275 ::boxology_contract::PathSegment::Field(
1276 "span_end_line".into(),
1277 ),
1278 )
1279 })?,
1280 span_end_column: <::core::option::Option<
1281 u64,
1282 > as ::boxology_contract::ContractType>::decode_field(
1283 fields.get("span_end_column"),
1284 )
1285 .map_err(|error| {
1286 error
1287 .under(
1288 ::boxology_contract::PathSegment::Field(
1289 "span_end_column".into(),
1290 ),
1291 )
1292 })?,
1293 offending: <::core::option::Option<
1294 ::std::string::String,
1295 > as ::boxology_contract::ContractType>::decode_field(
1296 fields.get("offending"),
1297 )
1298 .map_err(|error| {
1299 error
1300 .under(
1301 ::boxology_contract::PathSegment::Field("offending".into()),
1302 )
1303 })?,
1304 class: <::core::option::Option<
1305 ::std::string::String,
1306 > as ::boxology_contract::ContractType>::decode_field(fields.get("class"))
1307 .map_err(|error| {
1308 error.under(::boxology_contract::PathSegment::Field("class".into()))
1309 })?,
1310 condition: <::core::option::Option<
1311 ::std::string::String,
1312 > as ::boxology_contract::ContractType>::decode_field(
1313 fields.get("condition"),
1314 )
1315 .map_err(|error| {
1316 error
1317 .under(
1318 ::boxology_contract::PathSegment::Field("condition".into()),
1319 )
1320 })?,
1321 })
1322 }
1323}
1324#[derive(Debug, Clone, PartialEq)]
1325pub struct CheckStepReport {
1326 pub id: ::std::string::String,
1327 pub status: CheckStepStatus,
1328 pub reason: ::core::option::Option<::std::string::String>,
1329 pub findings: ::std::vec::Vec<CheckFinding>,
1330 pub output: ::core::option::Option<::std::vec::Vec<u8>>,
1331}
1332impl ::boxology_contract::ContractType for CheckStepReport {
1333 fn encode_value(
1334 &self,
1335 ) -> ::core::result::Result<
1336 ::boxology_contract::ContractValue,
1337 ::boxology_contract::EncodeError,
1338 > {
1339 let mut fields = ::std::vec::Vec::new();
1340 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.id)
1341 .map_err(|error| {
1342 error.under(::boxology_contract::PathSegment::Field("id".into()))
1343 })?
1344 {
1345 fields.push(("id".into(), value));
1346 }
1347 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1348 &self.status,
1349 )
1350 .map_err(|error| {
1351 error.under(::boxology_contract::PathSegment::Field("status".into()))
1352 })?
1353 {
1354 fields.push(("status".into(), value));
1355 }
1356 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1357 &self.reason,
1358 )
1359 .map_err(|error| {
1360 error.under(::boxology_contract::PathSegment::Field("reason".into()))
1361 })?
1362 {
1363 fields.push(("reason".into(), value));
1364 }
1365 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1366 &self.findings,
1367 )
1368 .map_err(|error| {
1369 error.under(::boxology_contract::PathSegment::Field("findings".into()))
1370 })?
1371 {
1372 fields.push(("findings".into(), value));
1373 }
1374 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1375 &self.output,
1376 )
1377 .map_err(|error| {
1378 error.under(::boxology_contract::PathSegment::Field("output".into()))
1379 })?
1380 {
1381 fields.push(("output".into(), value));
1382 }
1383 ::boxology_contract::ContractValue::object(fields)
1384 .map_err(|_| unreachable!("validated generated field identities are unique"))
1385 }
1386 fn decode_value(
1387 value: &::boxology_contract::ContractValue,
1388 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1389 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
1390 return Err(
1391 ::boxology_contract::DecodeError::new(
1392 ::boxology_contract::DecodeErrorKind::KindMismatch,
1393 ),
1394 );
1395 };
1396 for (field, _) in fields.entries() {
1397 match field {
1398 "id" | "status" | "reason" | "findings" | "output" => {}
1399 _ => {
1400 return Err(
1401 ::boxology_contract::DecodeError::new(
1402 ::boxology_contract::DecodeErrorKind::UnknownField(
1403 field.into(),
1404 ),
1405 )
1406 .under(::boxology_contract::PathSegment::Field(field.into())),
1407 );
1408 }
1409 }
1410 }
1411 Ok(Self {
1412 id: <::std::string::String as ::boxology_contract::ContractType>::decode_field(
1413 fields.get("id"),
1414 )
1415 .map_err(|error| {
1416 error.under(::boxology_contract::PathSegment::Field("id".into()))
1417 })?,
1418 status: <CheckStepStatus as ::boxology_contract::ContractType>::decode_field(
1419 fields.get("status"),
1420 )
1421 .map_err(|error| {
1422 error.under(::boxology_contract::PathSegment::Field("status".into()))
1423 })?,
1424 reason: <::core::option::Option<
1425 ::std::string::String,
1426 > as ::boxology_contract::ContractType>::decode_field(fields.get("reason"))
1427 .map_err(|error| {
1428 error.under(::boxology_contract::PathSegment::Field("reason".into()))
1429 })?,
1430 findings: <::std::vec::Vec<
1431 CheckFinding,
1432 > as ::boxology_contract::ContractType>::decode_field(fields.get("findings"))
1433 .map_err(|error| {
1434 error
1435 .under(
1436 ::boxology_contract::PathSegment::Field("findings".into()),
1437 )
1438 })?,
1439 output: <::core::option::Option<
1440 ::std::vec::Vec<u8>,
1441 > as ::boxology_contract::ContractType>::decode_field(fields.get("output"))
1442 .map_err(|error| {
1443 error.under(::boxology_contract::PathSegment::Field("output".into()))
1444 })?,
1445 })
1446 }
1447}
1448#[derive(Debug, Clone, PartialEq)]
1449pub struct CheckReport {
1450 pub steps: ::std::vec::Vec<CheckStepReport>,
1451 pub status: CheckStatus,
1452 pub human: ::std::vec::Vec<u8>,
1453 pub json: ::std::vec::Vec<u8>,
1454}
1455impl ::boxology_contract::ContractType for CheckReport {
1456 fn encode_value(
1457 &self,
1458 ) -> ::core::result::Result<
1459 ::boxology_contract::ContractValue,
1460 ::boxology_contract::EncodeError,
1461 > {
1462 let mut fields = ::std::vec::Vec::new();
1463 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.steps)
1464 .map_err(|error| {
1465 error.under(::boxology_contract::PathSegment::Field("steps".into()))
1466 })?
1467 {
1468 fields.push(("steps".into(), value));
1469 }
1470 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1471 &self.status,
1472 )
1473 .map_err(|error| {
1474 error.under(::boxology_contract::PathSegment::Field("status".into()))
1475 })?
1476 {
1477 fields.push(("status".into(), value));
1478 }
1479 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.human)
1480 .map_err(|error| {
1481 error.under(::boxology_contract::PathSegment::Field("human".into()))
1482 })?
1483 {
1484 fields.push(("human".into(), value));
1485 }
1486 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.json)
1487 .map_err(|error| {
1488 error.under(::boxology_contract::PathSegment::Field("json".into()))
1489 })?
1490 {
1491 fields.push(("json".into(), value));
1492 }
1493 ::boxology_contract::ContractValue::object(fields)
1494 .map_err(|_| unreachable!("validated generated field identities are unique"))
1495 }
1496 fn decode_value(
1497 value: &::boxology_contract::ContractValue,
1498 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1499 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
1500 return Err(
1501 ::boxology_contract::DecodeError::new(
1502 ::boxology_contract::DecodeErrorKind::KindMismatch,
1503 ),
1504 );
1505 };
1506 for (field, _) in fields.entries() {
1507 match field {
1508 "steps" | "status" | "human" | "json" => {}
1509 _ => {
1510 return Err(
1511 ::boxology_contract::DecodeError::new(
1512 ::boxology_contract::DecodeErrorKind::UnknownField(
1513 field.into(),
1514 ),
1515 )
1516 .under(::boxology_contract::PathSegment::Field(field.into())),
1517 );
1518 }
1519 }
1520 }
1521 Ok(Self {
1522 steps: <::std::vec::Vec<
1523 CheckStepReport,
1524 > as ::boxology_contract::ContractType>::decode_field(fields.get("steps"))
1525 .map_err(|error| {
1526 error.under(::boxology_contract::PathSegment::Field("steps".into()))
1527 })?,
1528 status: <CheckStatus as ::boxology_contract::ContractType>::decode_field(
1529 fields.get("status"),
1530 )
1531 .map_err(|error| {
1532 error.under(::boxology_contract::PathSegment::Field("status".into()))
1533 })?,
1534 human: <::std::vec::Vec<
1535 u8,
1536 > as ::boxology_contract::ContractType>::decode_field(fields.get("human"))
1537 .map_err(|error| {
1538 error.under(::boxology_contract::PathSegment::Field("human".into()))
1539 })?,
1540 json: <::std::vec::Vec<
1541 u8,
1542 > as ::boxology_contract::ContractType>::decode_field(fields.get("json"))
1543 .map_err(|error| {
1544 error.under(::boxology_contract::PathSegment::Field("json".into()))
1545 })?,
1546 })
1547 }
1548}
1549#[derive(Debug, Clone, PartialEq)]
1550pub struct CheckFailure {
1551 pub kind: CheckFailureKind,
1552 pub human: ::std::vec::Vec<u8>,
1553 pub json: ::std::vec::Vec<u8>,
1554}
1555impl ::boxology_contract::ContractType for CheckFailure {
1556 fn encode_value(
1557 &self,
1558 ) -> ::core::result::Result<
1559 ::boxology_contract::ContractValue,
1560 ::boxology_contract::EncodeError,
1561 > {
1562 let mut fields = ::std::vec::Vec::new();
1563 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.kind)
1564 .map_err(|error| {
1565 error.under(::boxology_contract::PathSegment::Field("kind".into()))
1566 })?
1567 {
1568 fields.push(("kind".into(), value));
1569 }
1570 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.human)
1571 .map_err(|error| {
1572 error.under(::boxology_contract::PathSegment::Field("human".into()))
1573 })?
1574 {
1575 fields.push(("human".into(), value));
1576 }
1577 if let Some(value) = ::boxology_contract::ContractType::encode_field(&self.json)
1578 .map_err(|error| {
1579 error.under(::boxology_contract::PathSegment::Field("json".into()))
1580 })?
1581 {
1582 fields.push(("json".into(), value));
1583 }
1584 ::boxology_contract::ContractValue::object(fields)
1585 .map_err(|_| unreachable!("validated generated field identities are unique"))
1586 }
1587 fn decode_value(
1588 value: &::boxology_contract::ContractValue,
1589 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1590 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
1591 return Err(
1592 ::boxology_contract::DecodeError::new(
1593 ::boxology_contract::DecodeErrorKind::KindMismatch,
1594 ),
1595 );
1596 };
1597 for (field, _) in fields.entries() {
1598 match field {
1599 "kind" | "human" | "json" => {}
1600 _ => {
1601 return Err(
1602 ::boxology_contract::DecodeError::new(
1603 ::boxology_contract::DecodeErrorKind::UnknownField(
1604 field.into(),
1605 ),
1606 )
1607 .under(::boxology_contract::PathSegment::Field(field.into())),
1608 );
1609 }
1610 }
1611 }
1612 Ok(Self {
1613 kind: <CheckFailureKind as ::boxology_contract::ContractType>::decode_field(
1614 fields.get("kind"),
1615 )
1616 .map_err(|error| {
1617 error.under(::boxology_contract::PathSegment::Field("kind".into()))
1618 })?,
1619 human: <::std::vec::Vec<
1620 u8,
1621 > as ::boxology_contract::ContractType>::decode_field(fields.get("human"))
1622 .map_err(|error| {
1623 error.under(::boxology_contract::PathSegment::Field("human".into()))
1624 })?,
1625 json: <::std::vec::Vec<
1626 u8,
1627 > as ::boxology_contract::ContractType>::decode_field(fields.get("json"))
1628 .map_err(|error| {
1629 error.under(::boxology_contract::PathSegment::Field("json".into()))
1630 })?,
1631 })
1632 }
1633}
1634#[derive(Debug, Clone, PartialEq)]
1635pub struct CheckOutcome {
1636 pub report: ::core::option::Option<CheckReport>,
1637 pub failure: ::core::option::Option<CheckFailure>,
1638}
1639impl ::boxology_contract::ContractType for CheckOutcome {
1640 fn encode_value(
1641 &self,
1642 ) -> ::core::result::Result<
1643 ::boxology_contract::ContractValue,
1644 ::boxology_contract::EncodeError,
1645 > {
1646 let mut fields = ::std::vec::Vec::new();
1647 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1648 &self.report,
1649 )
1650 .map_err(|error| {
1651 error.under(::boxology_contract::PathSegment::Field("report".into()))
1652 })?
1653 {
1654 fields.push(("report".into(), value));
1655 }
1656 if let Some(value) = ::boxology_contract::ContractType::encode_field(
1657 &self.failure,
1658 )
1659 .map_err(|error| {
1660 error.under(::boxology_contract::PathSegment::Field("failure".into()))
1661 })?
1662 {
1663 fields.push(("failure".into(), value));
1664 }
1665 ::boxology_contract::ContractValue::object(fields)
1666 .map_err(|_| unreachable!("validated generated field identities are unique"))
1667 }
1668 fn decode_value(
1669 value: &::boxology_contract::ContractValue,
1670 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1671 let ::boxology_contract::ValueRef::Object(fields) = value.view() else {
1672 return Err(
1673 ::boxology_contract::DecodeError::new(
1674 ::boxology_contract::DecodeErrorKind::KindMismatch,
1675 ),
1676 );
1677 };
1678 for (field, _) in fields.entries() {
1679 match field {
1680 "report" | "failure" => {}
1681 _ => {
1682 return Err(
1683 ::boxology_contract::DecodeError::new(
1684 ::boxology_contract::DecodeErrorKind::UnknownField(
1685 field.into(),
1686 ),
1687 )
1688 .under(::boxology_contract::PathSegment::Field(field.into())),
1689 );
1690 }
1691 }
1692 }
1693 Ok(Self {
1694 report: <::core::option::Option<
1695 CheckReport,
1696 > as ::boxology_contract::ContractType>::decode_field(fields.get("report"))
1697 .map_err(|error| {
1698 error.under(::boxology_contract::PathSegment::Field("report".into()))
1699 })?,
1700 failure: <::core::option::Option<
1701 CheckFailure,
1702 > as ::boxology_contract::ContractType>::decode_field(fields.get("failure"))
1703 .map_err(|error| {
1704 error
1705 .under(::boxology_contract::PathSegment::Field("failure".into()))
1706 })?,
1707 })
1708 }
1709}
1710#[derive(Debug, Clone, PartialEq)]
1711pub enum CheckError {
1712 Internal,
1713 Unknown { tag: ::std::string::String, payload: ::boxology_contract::OpaquePayload },
1714}
1715impl ::boxology_contract::ContractType for CheckError {
1716 fn encode_value(
1717 &self,
1718 ) -> ::core::result::Result<
1719 ::boxology_contract::ContractValue,
1720 ::boxology_contract::EncodeError,
1721 > {
1722 let (tag, payload) = match self {
1723 Self::Internal => ("Internal".into(), ::boxology_contract::SlotValue::Null),
1724 Self::Unknown { tag, payload } => {
1725 (
1726 tag.clone(),
1727 ::boxology_contract::SlotValue::Value(
1728 ::boxology_contract::ContractValue::opaque(payload.forward()),
1729 ),
1730 )
1731 }
1732 };
1733 Ok(::boxology_contract::ContractValue::enum_value(tag, payload))
1734 }
1735 fn decode_value(
1736 value: &::boxology_contract::ContractValue,
1737 ) -> ::core::result::Result<Self, ::boxology_contract::DecodeError> {
1738 let ::boxology_contract::ValueRef::Enum { tag, payload } = value.view() else {
1739 return Err(
1740 ::boxology_contract::DecodeError::new(
1741 ::boxology_contract::DecodeErrorKind::KindMismatch,
1742 ),
1743 );
1744 };
1745 match tag {
1746 "Internal" if matches!(payload, ::boxology_contract::SlotValue::Null) => {
1747 Ok(Self::Internal)
1748 }
1749 "Internal" => {
1750 Err(
1751 ::boxology_contract::DecodeError::new(
1752 ::boxology_contract::DecodeErrorKind::UnexpectedPayload,
1753 )
1754 .under(::boxology_contract::PathSegment::Variant(tag.into())),
1755 )
1756 }
1757 _ => {
1758 match payload {
1759 ::boxology_contract::SlotValue::Value(value) => {
1760 match value.view() {
1761 ::boxology_contract::ValueRef::Opaque(payload) => {
1762 Ok(Self::Unknown {
1763 tag: tag.into(),
1764 payload: payload.forward(),
1765 })
1766 }
1767 _ => {
1768 Err(
1769 ::boxology_contract::DecodeError::new(
1770 ::boxology_contract::DecodeErrorKind::UnknownVariant(
1771 tag.into(),
1772 ),
1773 )
1774 .under(
1775 ::boxology_contract::PathSegment::Variant(tag.into()),
1776 ),
1777 )
1778 }
1779 }
1780 }
1781 _ => {
1782 Err(
1783 ::boxology_contract::DecodeError::new(
1784 ::boxology_contract::DecodeErrorKind::UnknownVariant(
1785 tag.into(),
1786 ),
1787 )
1788 .under(
1789 ::boxology_contract::PathSegment::Variant(tag.into()),
1790 ),
1791 )
1792 }
1793 }
1794 }
1795 }
1796 }
1797}
1798impl ::boxology_contract::ContractError for CheckError {
1799 fn error_tag(&self) -> &str {
1800 match self {
1801 Self::Internal => "Internal",
1802 Self::Unknown { tag, .. } => tag,
1803 }
1804 }
1805}
1806#[cfg(feature = "test-support")]
1807pub mod test_support {
1808 use std::future::{Future, ready};
1809 use std::pin::Pin;
1810 use std::sync::Arc;
1811 use ::boxology_contract::{
1812 CallContext, CapabilityId, ContractType, DecodeRole, Detail, ErasedCallError,
1813 ErasedCallTarget, SlotValue, TypeDescriptor,
1814 };
1815 use super::{CheckError, CHECK_CHECK, CheckHandle, conversion_detail};
1816 type CheckFuture = Pin<
1817 Box<
1818 dyn Future<Output = Result<super::CheckOutcome, CheckError>> + Send + 'static,
1819 >,
1820 >;
1821 type CheckResponder = dyn Fn(
1822 CallContext,
1823 super::CheckRequest,
1824 ) -> CheckFuture + Send + Sync + 'static;
1825 #[derive(Clone, Default)]
1826 pub struct CheckFake {
1827 check: Option<Arc<CheckResponder>>,
1828 }
1829 impl CheckFake {
1830 pub fn new() -> Self {
1831 Self::default()
1832 }
1833 pub fn with_check<F, Fut>(mut self, responder: F) -> Self
1834 where
1835 F: Fn(CallContext, super::CheckRequest) -> Fut + Send + Sync + 'static,
1836 Fut: Future<Output = Result<super::CheckOutcome, CheckError>> + Send
1837 + 'static,
1838 {
1839 self.check = Some(
1840 Arc::new(move |context, request| {
1841 Box::pin(responder(context, request))
1842 }),
1843 );
1844 self
1845 }
1846 pub fn handle(&self) -> CheckHandle {
1847 CheckHandle::from_erased(Arc::new(self.clone()))
1848 }
1849 }
1850 impl ErasedCallTarget for CheckFake {
1851 fn call<'a>(
1852 &'a self,
1853 capability: &'a CapabilityId,
1854 context: CallContext,
1855 input: SlotValue,
1856 ) -> Pin<
1857 Box<dyn Future<Output = Result<SlotValue, ErasedCallError>> + Send + 'a>,
1858 > {
1859 if capability != &*CHECK_CHECK {
1860 return Box::pin(ready(Err(unprogrammed())));
1861 }
1862 let Some(responder) = self.check.clone() else {
1863 return Box::pin(ready(Err(unprogrammed())));
1864 };
1865 Box::pin(async move {
1866 let input = TypeDescriptor::structure([
1867 ::boxology_contract::FieldDescriptor::new(
1868 "workspace",
1869 TypeDescriptor::string(),
1870 None,
1871 ),
1872 ::boxology_contract::FieldDescriptor::new(
1873 "base",
1874 TypeDescriptor::optional(TypeDescriptor::string())
1875 .expect("generated optional descriptor is valid"),
1876 None,
1877 ),
1878 ])
1879 .expect("generated struct descriptor is valid")
1880 .conform(DecodeRole::ProviderInput, input)
1881 .map_err(|error| {
1882 ErasedCallError::ContractViolation(
1883 conversion_detail("input_decode", error),
1884 )
1885 })?;
1886 let request = <super::CheckRequest as ContractType>::decode(&input)
1887 .map_err(|error| {
1888 ErasedCallError::ContractViolation(
1889 conversion_detail("input_decode", error),
1890 )
1891 })?;
1892 match responder(context, request).await {
1893 Ok(output) => {
1894 output
1895 .encode()
1896 .map_err(|error| {
1897 ErasedCallError::InvalidResponse(
1898 conversion_detail("output_encode", error),
1899 )
1900 })
1901 }
1902 Err(error) => Err(ErasedCallError::from_domain(&error)),
1903 }
1904 })
1905 }
1906 }
1907 fn unprogrammed() -> ErasedCallError {
1908 ErasedCallError::Internal(Detail::new("unprogrammed_capability"))
1909 }
1910}
1911#[doc(hidden)]
1912pub const __BOXOLOGY_SEMANTIC_DIGEST: [u8; 32] = [
1913 2, 77, 0, 140, 120, 151, 105, 218, 107, 123, 130, 202, 34, 9, 233, 42, 222, 179, 217,
1914 54, 168, 241, 90, 245, 73, 49, 119, 39, 144, 105, 131, 72,
1915];
1916#[doc(hidden)]
1917#[macro_export]
1918macro_rules! __boxology_check_implementation {
1919 ($receiver:ty; $($method:ident $validity:ident;)*) => {
1920 $crate::__boxology_check_implementation!(@ find $receiver; $($method
1921 $validity;)*);
1922 };
1923 (@ find $receiver:ty; check valid; $($rest:tt)*) => {
1924 const _ : () = { fn require_service < T : ::core::marker::Send +
1925 ::core::marker::Sync + 'static > () {} fn require_future < F :
1926 ::core::future::Future < Output = ::core::result::Result <$crate::CheckOutcome,
1927 $crate::CheckError >> + ::core::marker::Send > (_ : F) {} fn check(receiver :
1928 &$receiver, context : ::boxology::CallContext, input : $crate::CheckRequest) {
1929 require_service::<$receiver > (); require_future(receiver.check(context, input));
1930 } }; impl $crate::CheckDispatch for $receiver { fn check <'a > (&'a self, context
1931 : ::boxology::CallContext, input : $crate::CheckRequest,) -> ::std::pin::Pin <
1932 ::std::boxed::Box < dyn ::core::future::Future < Output = ::core::result::Result
1933 < $crate::CheckOutcome, $crate::CheckError, >, > + ::core::marker::Send + 'a, >,
1934 > { ::std::boxed::Box::pin(self.check(context, input)) } }
1935 };
1936 (@ find $receiver:ty; check invalid; $($rest:tt)*) => {
1937 compile_error!("Boxology capability has an invalid structural signature");
1938 };
1939 (@ find $receiver:ty; $other:ident $validity:ident; $($rest:tt)*) => {
1940 $crate::__boxology_check_implementation!(@ find $receiver; $($rest)*);
1941 };
1942 (@ find $receiver:ty;) => {
1943 compile_error!("Boxology capability implementation is missing");
1944 };
1945}