1#![cfg_attr(not(test), deny(clippy::cast_possible_truncation))]
54#![cfg_attr(not(test), deny(clippy::cast_possible_wrap))]
55#![cfg_attr(feature = "rpc_try", feature(try_trait_v2))]
56#![cfg_attr(not(feature = "std"), no_std)]
57
58#[cfg(feature = "alloc")]
59#[macro_use]
60extern crate alloc;
61
62pub mod schema_capnp;
65
66pub mod any_pointer;
67pub mod any_pointer_list;
68pub mod capability;
69pub mod capability_list;
70pub mod constant;
71pub mod data;
72pub mod data_list;
73pub mod dynamic_list;
74pub mod dynamic_struct;
75pub mod dynamic_value;
76pub mod enum_list;
77pub mod introspect;
78pub mod io;
79pub mod list_list;
80pub mod message;
81pub mod primitive_list;
82pub mod private;
83pub mod raw;
84pub mod schema;
85pub mod serialize;
86pub mod serialize_packed;
87pub(crate) mod stringify;
88pub mod struct_list;
89pub mod text;
90pub mod text_list;
91pub mod traits;
92
93#[macro_export]
110macro_rules! generated_code {
111 ($vis:vis mod $mod_name:ident, $file_name:expr) => {
112 $vis mod $mod_name {
113 #![allow(clippy::all)]
114 include!(concat!(env!("OUT_DIR"), "/", $file_name));
115 }
116 };
117
118 ($vis:vis mod $mod_name:ident) => {
119 $crate::generated_code!($vis mod $mod_name, concat!(stringify!($mod_name), ".rs"));
120 };
121}
122
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
129#[repr(C, align(8))]
130pub struct Word {
131 raw_content: [u8; 8],
132}
133
134#[allow(clippy::too_many_arguments)]
138pub const fn word(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8, b6: u8, b7: u8) -> Word {
139 Word {
140 raw_content: [b0, b1, b2, b3, b4, b5, b6, b7],
141 }
142}
143
144impl Word {
145 #[cfg(feature = "alloc")]
147 pub fn allocate_zeroed_vec(length: usize) -> alloc::vec::Vec<Self> {
148 vec![word(0, 0, 0, 0, 0, 0, 0, 0); length]
149 }
150
151 pub fn words_to_bytes(words: &[Self]) -> &[u8] {
152 unsafe { core::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8) }
153 }
154
155 pub fn words_to_bytes_mut(words: &mut [Self]) -> &mut [u8] {
156 unsafe { core::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8) }
157 }
158}
159
160#[cfg(any(feature = "quickcheck", test))]
161impl quickcheck::Arbitrary for Word {
162 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
163 crate::word(
164 quickcheck::Arbitrary::arbitrary(g),
165 quickcheck::Arbitrary::arbitrary(g),
166 quickcheck::Arbitrary::arbitrary(g),
167 quickcheck::Arbitrary::arbitrary(g),
168 quickcheck::Arbitrary::arbitrary(g),
169 quickcheck::Arbitrary::arbitrary(g),
170 quickcheck::Arbitrary::arbitrary(g),
171 quickcheck::Arbitrary::arbitrary(g),
172 )
173 }
174}
175
176#[derive(Clone, Copy, Debug, PartialEq)]
178pub struct MessageSize {
179 pub word_count: u64,
180
181 pub cap_count: u32,
183}
184
185impl core::ops::AddAssign for MessageSize {
186 fn add_assign(&mut self, rhs: Self) {
187 self.word_count += rhs.word_count;
188 self.cap_count += rhs.cap_count;
189 }
190}
191
192#[derive(PartialEq, Eq, Clone, Copy, Debug)]
194pub struct NotInSchema(pub u16);
195
196impl ::core::fmt::Display for NotInSchema {
197 fn fmt(
198 &self,
199 fmt: &mut ::core::fmt::Formatter,
200 ) -> ::core::result::Result<(), ::core::fmt::Error> {
201 write!(
202 fmt,
203 "Enum value or union discriminant {} was not present in the schema.",
204 self.0
205 )
206 }
207}
208
209impl ::core::error::Error for NotInSchema {
210 fn description(&self) -> &str {
211 "Enum value or union discriminant was not present in schema."
212 }
213}
214
215pub type Result<T> = ::core::result::Result<T, Error>;
218
219#[derive(Debug, Clone)]
221pub struct Error {
222 pub kind: ErrorKind,
225
226 #[cfg(feature = "alloc")]
228 pub extra: alloc::string::String,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234#[non_exhaustive]
235pub enum ErrorKind {
236 Failed,
238
239 Overloaded,
246
247 Disconnected,
250
251 Unimplemented,
254
255 BufferNotLargeEnough,
257
258 CannotCreateACanonicalMessageWithACapability,
260
261 CannotSetAnyPointerFieldToAPrimitiveValue,
263
264 CantHandleNonStructInlineComposite,
266
267 EmptyBuffer,
269
270 EmptySlice,
272
273 EnumValueOrUnionDiscriminantNotPresent(NotInSchema),
275
276 ExistingListPointerIsNotByteSized,
278
279 ExistingListValueIsIncompatibleWithExpectedType,
281
282 ExistingPointerIsNotAList,
284
285 ExpectedAListOrBlob,
287
288 ExpectedAPointerListButGotAListOfDataOnlyStructs,
290
291 ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs,
293
294 FailedToFillTheWholeBuffer,
296
297 FieldAndDefaultMismatch,
299
300 FieldNotFound,
302
303 FoundBitListWhereStructListWasExpected,
305
306 FoundStructListWhereBitListWasExpected,
308
309 FourByteLengthTooBigForUSize,
311
312 FourByteSegmentLengthTooBigForUSize,
314
315 GroupFieldButTypeIsNotStruct,
317
318 InitIsOnlyValidForStructAndAnyPointerFields,
320
321 InitnIsOnlyValidForListTextOrDataFields,
323
324 InlineCompositeListWithNonStructElementsNotSupported,
326
327 InlineCompositeListsElementsOverrunItsWordCount,
329
330 InlineCompositeListsOfNonStructTypeAreNotSupported,
332
333 InvalidNumberOfSegments(usize),
335
336 InvalidSegmentId(u32),
338
339 ListAnyPointerNotSupported,
341
342 ListCapabilityNotSupported,
344
345 MalformedDoubleFarPointer,
347
348 MessageContainsInvalidCapabilityPointer,
350
351 MessageContainsListPointerOfNonBytesWhereDataWasExpected,
353
354 MessageContainsListPointerOfNonBytesWhereTextWasExpected,
356
357 MessageContainsListWithIncompatibleElementType,
359
360 MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected,
362
363 MessageContainsNonStructPointerWhereStructPointerWasExpected,
365
366 MessageContainsNonListPointerWhereDataWasExpected,
368
369 MessageContainsNonListPointerWhereListPointerWasExpected,
371
372 MessageContainsNonListPointerWhereTextWasExpected,
374
375 MessageContainsNullCapabilityPointer,
377
378 MessageContainsOutOfBoundsPointer,
380
381 MessageContainsTextThatIsNotNULTerminated,
383
384 MessageEndsPrematurely(usize, usize),
386
387 MessageIsTooDeeplyNested,
389
390 MessageIsTooDeeplyNestedOrContainsCycles,
392
393 MessageNotAlignedBy8BytesBoundary,
395
396 MessageSizeOverflow,
398
399 MessageTooLarge(usize),
401
402 NestingLimitExceeded,
404
405 NotAStruct,
407
408 OnlyOneOfTheSectionPointersIsPointingToOurself,
410
411 PackedInputDidNotEndCleanlyOnASegmentBoundary,
413
414 PrematureEndOfFile,
416
417 PrematureEndOfPackedInput,
419
420 ReadLimitExceeded,
422
423 SettingDynamicCapabilitiesIsUnsupported,
425
426 StructReaderHadBitwidthOtherThan1,
428
429 TextBlobMissingNULTerminator,
431
432 TextContainsNonUtf8Data(core::str::Utf8Error),
434
435 TriedToReadFromNullArena,
437
438 TypeMismatch,
440
441 UnalignedSegment,
444
445 UnexpectedFarPointer,
447
448 UnknownPointerType,
450}
451
452impl Error {
453 pub fn write_fmt(&mut self, fmt: core::fmt::Arguments<'_>) {
456 #[cfg(feature = "alloc")]
457 {
458 use core::fmt::Write;
459 let _ = self.extra.write_fmt(fmt);
460 }
461 }
462
463 #[cfg(feature = "alloc")]
464 pub fn failed(description: alloc::string::String) -> Self {
465 Self {
466 extra: description,
467 kind: ErrorKind::Failed,
468 }
469 }
470
471 pub fn from_kind(kind: ErrorKind) -> Self {
472 #[cfg(not(feature = "alloc"))]
473 return Self { kind };
474 #[cfg(feature = "alloc")]
475 return Self {
476 kind,
477 extra: alloc::string::String::new(),
478 };
479 }
480
481 #[cfg(feature = "alloc")]
482 pub fn overloaded(description: alloc::string::String) -> Self {
483 Self {
484 extra: description,
485 kind: ErrorKind::Overloaded,
486 }
487 }
488 #[cfg(feature = "alloc")]
489 pub fn disconnected(description: alloc::string::String) -> Self {
490 Self {
491 extra: description,
492 kind: ErrorKind::Disconnected,
493 }
494 }
495
496 #[cfg(feature = "alloc")]
497 pub fn unimplemented(description: alloc::string::String) -> Self {
498 Self {
499 extra: description,
500 kind: ErrorKind::Unimplemented,
501 }
502 }
503}
504
505#[cfg(feature = "std")]
506impl core::convert::From<::std::io::Error> for Error {
507 fn from(err: ::std::io::Error) -> Self {
508 use std::io;
509 let kind = match err.kind() {
510 io::ErrorKind::TimedOut => ErrorKind::Overloaded,
511 io::ErrorKind::BrokenPipe
512 | io::ErrorKind::ConnectionRefused
513 | io::ErrorKind::ConnectionReset
514 | io::ErrorKind::ConnectionAborted
515 | io::ErrorKind::NotConnected => ErrorKind::Disconnected,
516 io::ErrorKind::UnexpectedEof => ErrorKind::PrematureEndOfFile,
517 _ => ErrorKind::Failed,
518 };
519 #[cfg(feature = "alloc")]
520 return Self {
521 kind,
522 extra: format!("{err}"),
523 };
524 #[cfg(not(feature = "alloc"))]
525 return Self { kind };
526 }
527}
528
529#[cfg(feature = "embedded-io")]
530impl From<embedded_io::ErrorKind> for ErrorKind {
531 fn from(value: embedded_io::ErrorKind) -> Self {
532 match value {
533 embedded_io::ErrorKind::Other => Self::Failed,
534 embedded_io::ErrorKind::NotFound => Self::Failed,
535 embedded_io::ErrorKind::PermissionDenied => Self::Failed,
536 embedded_io::ErrorKind::ConnectionRefused => Self::Failed,
537 embedded_io::ErrorKind::ConnectionReset => Self::Failed,
538 embedded_io::ErrorKind::ConnectionAborted => Self::Failed,
539 embedded_io::ErrorKind::NotConnected => Self::Failed,
540 embedded_io::ErrorKind::AddrInUse => Self::Failed,
541 embedded_io::ErrorKind::AddrNotAvailable => Self::Failed,
542 embedded_io::ErrorKind::BrokenPipe => Self::Failed,
543 embedded_io::ErrorKind::AlreadyExists => Self::Failed,
544 embedded_io::ErrorKind::InvalidInput => Self::Failed,
545 embedded_io::ErrorKind::InvalidData => Self::Failed,
546 embedded_io::ErrorKind::TimedOut => Self::Failed,
547 embedded_io::ErrorKind::Interrupted => Self::Failed,
548 embedded_io::ErrorKind::Unsupported => Self::Failed,
549 embedded_io::ErrorKind::OutOfMemory => Self::Failed,
550 _ => Self::Failed,
551 }
552 }
553}
554
555#[cfg(feature = "alloc")]
556impl core::convert::From<alloc::string::FromUtf8Error> for Error {
557 fn from(err: alloc::string::FromUtf8Error) -> Self {
558 Self::failed(format!("{err}"))
559 }
560}
561
562impl core::convert::From<core::str::Utf8Error> for Error {
563 fn from(err: core::str::Utf8Error) -> Self {
564 Self::from_kind(ErrorKind::TextContainsNonUtf8Data(err))
565 }
566}
567
568impl core::convert::From<NotInSchema> for Error {
569 fn from(e: NotInSchema) -> Self {
570 Self::from_kind(ErrorKind::EnumValueOrUnionDiscriminantNotPresent(e))
571 }
572}
573
574impl core::fmt::Display for ErrorKind {
575 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
576 match self {
577 Self::Failed => write!(fmt, "Failed"),
578 Self::Overloaded => write!(fmt, "Overloaded"),
579 Self::Disconnected => write!(fmt, "Disconnected"),
580 Self::Unimplemented => write!(fmt, "Unimplemented"),
581 Self::BufferNotLargeEnough => write!(fmt, "buffer is not large enough"),
582 Self::ExistingListPointerIsNotByteSized => write!(fmt, "Called get_writable_{{data|text}}_pointer() but existing list pointer is not byte-sized."),
583 Self::ExistingPointerIsNotAList => write!(fmt, "Called get_writable_{{data|text|list|struct_list}}_pointer() but existing pointer is not a list."),
584 Self::CannotCreateACanonicalMessageWithACapability => write!(fmt, "Cannot create a canonical message with a capability"),
585 Self::FourByteLengthTooBigForUSize => write!(fmt, "Cannot represent 4 byte length as `usize`. This may indicate that you are running on 8 or 16 bit platform or message is too large."),
586 Self::FourByteSegmentLengthTooBigForUSize => write!(fmt, "Cannot represent 4 byte segment length as usize. This may indicate that you are running on 8 or 16 bit platform or segment is too large"),
587 Self::CannotSetAnyPointerFieldToAPrimitiveValue => write!(fmt, "cannot set AnyPointer field to a primitive value"),
588 Self::CantHandleNonStructInlineComposite => write!(fmt, "Don't know how to handle non-STRUCT inline composite."),
589 Self::EmptyBuffer => write!(fmt, "empty buffer"),
590 Self::EmptySlice => write!(fmt, "empty slice"),
591 Self::EnumValueOrUnionDiscriminantNotPresent(val) => write!(fmt, "Enum value or union discriminant {val} was not present in schema"),
592 Self::ExistingListValueIsIncompatibleWithExpectedType => write!(fmt, "Existing list value is incompatible with expected type."),
593 Self::ExpectedAListOrBlob => write!(fmt, "Expected a list or blob."),
594 Self::ExpectedAPointerListButGotAListOfDataOnlyStructs => write!(fmt, "Expected a pointer list, but got a list of data-only structs"),
595 Self::ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs => write!(fmt, "Expected a primitive list, but got a list of pointer-only structs"),
596 Self::FailedToFillTheWholeBuffer => write!(fmt, "failed to fill the whole buffer"),
597 Self::FieldAndDefaultMismatch => write!(fmt, "field and default mismatch"),
598 Self::FieldNotFound => write!(fmt, "field not found"),
599 Self::FoundBitListWhereStructListWasExpected => write!(fmt, "Found bit list where struct list was expected; upgrading boolean lists to struct lists is no longer supported."),
600 Self::FoundStructListWhereBitListWasExpected => write!(fmt, "Found struct list where bit list was expected."),
601 Self::GroupFieldButTypeIsNotStruct => write!(fmt, "group field but type is not Struct"),
602 Self::InitIsOnlyValidForStructAndAnyPointerFields => write!(fmt, "init() is only valid for struct and AnyPointer fields"),
603 Self::InitnIsOnlyValidForListTextOrDataFields => write!(fmt, "initn() is only valid for list, text, or data fields"),
604 Self::InlineCompositeListWithNonStructElementsNotSupported => write!(fmt, "InlineComposite list with non-STRUCT elements not supported."),
605 Self::InlineCompositeListsElementsOverrunItsWordCount => write!(fmt, "InlineComposite list's elements overrun its word count."),
606 Self::InlineCompositeListsOfNonStructTypeAreNotSupported => write!(fmt, "InlineComposite lists of non-STRUCT type are not supported."),
607 Self::InvalidNumberOfSegments(segment_count) => write!(fmt, "Too many or too few segments {segment_count}"),
608 Self::InvalidSegmentId(id) => write!(fmt, "Invalid segment id {id}"),
609 Self::ListAnyPointerNotSupported => write!(fmt, "List(AnyPointer) not supported."),
610 Self::ListCapabilityNotSupported => write!(fmt, "List(Capability) not supported"),
611 Self::MalformedDoubleFarPointer => write!(fmt, "Malformed double-far pointer."),
612 Self::MessageContainsInvalidCapabilityPointer => write!(fmt, "Message contained invalid capability pointer."),
613 Self::MessageContainsListPointerOfNonBytesWhereDataWasExpected => write!(fmt, "Message contains list pointer of non-bytes where data was expected."),
614 Self::MessageContainsListPointerOfNonBytesWhereTextWasExpected => write!(fmt, "Message contains list pointer of non-bytes where text was expected."),
615 Self::MessageContainsListWithIncompatibleElementType => write!(fmt, "Message contains list with incompatible element type."),
616 Self::MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected => write!(fmt, "Message contains non-capability pointer where capability pointer was expected."),
617 Self::MessageContainsNonListPointerWhereDataWasExpected => write!(fmt, "Message contains non-list pointer where data was expected."),
618 Self::MessageContainsNonListPointerWhereListPointerWasExpected => write!(fmt, "Message contains non-list pointer where list pointer was expected"),
619 Self::MessageContainsNonListPointerWhereTextWasExpected => write!(fmt, "Message contains non-list pointer where text was expected."),
620 Self::MessageContainsNonStructPointerWhereStructPointerWasExpected => write!(fmt, "Message contains non-struct pointer where struct pointer was expected."),
621 Self::MessageContainsNullCapabilityPointer => write!(fmt, "Message contains null capability pointer."),
622 Self::MessageContainsOutOfBoundsPointer => write!(fmt, "Message contains out-of-bounds pointer"),
623 Self::MessageContainsTextThatIsNotNULTerminated => write!(fmt, "Message contains text that is not NUL-terminated"),
624 Self::MessageEndsPrematurely(header, body) => write!(fmt, "Message ends prematurely. Header claimed {header} words, but message only has {body} words"),
625 Self::MessageIsTooDeeplyNested => write!(fmt, "Message is too deeply nested."),
626 Self::MessageIsTooDeeplyNestedOrContainsCycles => write!(fmt, "Message is too deeply-nested or contains cycles."),
627 Self::MessageSizeOverflow => write!(fmt, "Message's size cannot be represented in usize"),
628 Self::MessageTooLarge(val) => write!(fmt, "Message is too large: {val}"),
629 Self::MessageNotAlignedBy8BytesBoundary => write!(fmt, "Message was not aligned by 8 bytes boundary. Either ensure that message is properly aligned or compile `capnp` crate with \"unaligned\" feature enabled."),
630 Self::NestingLimitExceeded => write!(fmt, "nesting limit exceeded"),
631 Self::NotAStruct => write!(fmt, "not a struct"),
632 Self::OnlyOneOfTheSectionPointersIsPointingToOurself => write!(fmt, "Only one of the section pointers is pointing to ourself"),
633 Self::PackedInputDidNotEndCleanlyOnASegmentBoundary => write!(fmt, "Packed input did not end cleanly on a segment boundary."),
634 Self::PrematureEndOfFile => write!(fmt, "Premature end of file"),
635 Self::PrematureEndOfPackedInput => write!(fmt, "Premature end of packed input."),
636 Self::ReadLimitExceeded => write!(fmt, "Read limit exceeded"),
637 Self::SettingDynamicCapabilitiesIsUnsupported => write!(fmt, "setting dynamic capabilities is unsupported"),
638 Self::StructReaderHadBitwidthOtherThan1 => write!(fmt, "struct reader had bitwidth other than 1"),
639 Self::TextBlobMissingNULTerminator => write!(fmt, "Text blob missing NUL terminator."),
640 Self::TextContainsNonUtf8Data(e) => write!(fmt, "Text contains non-utf8 data: {e}"),
641 Self::TriedToReadFromNullArena => write!(fmt, "Tried to read from null arena"),
642 Self::TypeMismatch => write!(fmt, "type mismatch"),
643 Self::UnalignedSegment => write!(fmt, "Detected unaligned segment. You must either ensure all of your segments are 8-byte aligned, or you must enable the \"unaligned\" feature in the capnp crate"),
644 Self::UnexpectedFarPointer => write!(fmt, "Unexpected far pointer"),
645 Self::UnknownPointerType => write!(fmt, "Unknown pointer type."),
646 }
647 }
648}
649
650impl core::fmt::Display for Error {
651 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
652 #[cfg(feature = "alloc")]
653 let result = if self.extra.is_empty() {
654 write!(fmt, "{}", self.kind)
655 } else {
656 write!(fmt, "{}: {}", self.kind, self.extra)
657 };
658 #[cfg(not(feature = "alloc"))]
659 let result = write!(fmt, "{}", self.kind);
660 result
661 }
662}
663
664impl core::error::Error for Error {
665 #[cfg(feature = "alloc")]
666 fn description(&self) -> &str {
667 &self.extra
668 }
669 fn cause(&self) -> Option<&dyn ::core::error::Error> {
670 None
671 }
672}
673
674pub enum OutputSegments<'a> {
677 SingleSegment([&'a [u8]; 1]),
678
679 #[cfg(feature = "alloc")]
680 MultiSegment(alloc::vec::Vec<&'a [u8]>),
681}
682
683impl<'a> core::ops::Deref for OutputSegments<'a> {
684 type Target = [&'a [u8]];
685 fn deref(&self) -> &[&'a [u8]] {
686 match self {
687 OutputSegments::SingleSegment(s) => s,
688
689 #[cfg(feature = "alloc")]
690 OutputSegments::MultiSegment(v) => v,
691 }
692 }
693}
694
695impl message::ReaderSegments for OutputSegments<'_> {
696 fn get_segment(&self, id: u32) -> Option<&[u8]> {
697 match self {
698 OutputSegments::SingleSegment(s) => s.get(id as usize).copied(),
699
700 #[cfg(feature = "alloc")]
701 OutputSegments::MultiSegment(v) => v.get(id as usize).copied(),
702 }
703 }
704}