1#![cfg_attr(not(test), deny(clippy::cast_possible_truncation))]
30#![cfg_attr(feature = "rpc_try", feature(try_trait_v2))]
31#![cfg_attr(not(feature = "std"), no_std)]
32
33#[cfg(feature = "alloc")]
34#[macro_use]
35extern crate alloc;
36
37pub mod schema_capnp;
40
41pub mod any_pointer;
42pub mod any_pointer_list;
43pub mod capability;
44pub mod capability_list;
45pub mod constant;
46pub mod data;
47pub mod data_list;
48pub mod dynamic_list;
49pub mod dynamic_struct;
50pub mod dynamic_value;
51pub mod enum_list;
52pub mod introspect;
53pub mod io;
54pub mod list_list;
55pub mod message;
56pub mod primitive_list;
57pub mod private;
58pub mod raw;
59pub mod schema;
60pub mod serialize;
61pub mod serialize_packed;
62pub(crate) mod stringify;
63pub mod struct_list;
64pub mod text;
65pub mod text_list;
66pub mod traits;
67
68#[macro_export]
85macro_rules! generated_code {
86 ($vis:vis mod $mod_name:ident, $file_name:expr) => {
87 $vis mod $mod_name {
88 #![allow(clippy::all)]
89 include!(concat!(env!("OUT_DIR"), "/", $file_name));
90 }
91 };
92
93 ($vis:vis mod $mod_name:ident) => {
94 $crate::generated_code!($vis mod $mod_name, concat!(stringify!($mod_name), ".rs"));
95 };
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104#[repr(C, align(8))]
105pub struct Word {
106 raw_content: [u8; 8],
107}
108
109#[allow(clippy::too_many_arguments)]
113pub const fn word(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8, b6: u8, b7: u8) -> Word {
114 Word {
115 raw_content: [b0, b1, b2, b3, b4, b5, b6, b7],
116 }
117}
118
119impl Word {
120 #[cfg(feature = "alloc")]
122 pub fn allocate_zeroed_vec(length: usize) -> alloc::vec::Vec<Self> {
123 vec![word(0, 0, 0, 0, 0, 0, 0, 0); length]
124 }
125
126 pub fn words_to_bytes(words: &[Self]) -> &[u8] {
127 unsafe { core::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8) }
128 }
129
130 pub fn words_to_bytes_mut(words: &mut [Self]) -> &mut [u8] {
131 unsafe { core::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8) }
132 }
133}
134
135#[cfg(any(feature = "quickcheck", test))]
136impl quickcheck::Arbitrary for Word {
137 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
138 crate::word(
139 quickcheck::Arbitrary::arbitrary(g),
140 quickcheck::Arbitrary::arbitrary(g),
141 quickcheck::Arbitrary::arbitrary(g),
142 quickcheck::Arbitrary::arbitrary(g),
143 quickcheck::Arbitrary::arbitrary(g),
144 quickcheck::Arbitrary::arbitrary(g),
145 quickcheck::Arbitrary::arbitrary(g),
146 quickcheck::Arbitrary::arbitrary(g),
147 )
148 }
149}
150
151#[derive(Clone, Copy, Debug, PartialEq)]
153pub struct MessageSize {
154 pub word_count: u64,
155
156 pub cap_count: u32,
158}
159
160impl core::ops::AddAssign for MessageSize {
161 fn add_assign(&mut self, rhs: Self) {
162 self.word_count += rhs.word_count;
163 self.cap_count += rhs.cap_count;
164 }
165}
166
167#[derive(PartialEq, Eq, Clone, Copy, Debug)]
169pub struct NotInSchema(pub u16);
170
171impl ::core::fmt::Display for NotInSchema {
172 fn fmt(
173 &self,
174 fmt: &mut ::core::fmt::Formatter,
175 ) -> ::core::result::Result<(), ::core::fmt::Error> {
176 write!(
177 fmt,
178 "Enum value or union discriminant {} was not present in the schema.",
179 self.0
180 )
181 }
182}
183
184impl ::core::error::Error for NotInSchema {
185 fn description(&self) -> &str {
186 "Enum value or union discriminant was not present in schema."
187 }
188}
189
190pub type Result<T> = ::core::result::Result<T, Error>;
193
194#[derive(Debug, Clone)]
196pub struct Error {
197 pub kind: ErrorKind,
200
201 #[cfg(feature = "alloc")]
203 pub extra: alloc::string::String,
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209#[non_exhaustive]
210pub enum ErrorKind {
211 Failed,
213
214 Overloaded,
221
222 Disconnected,
225
226 Unimplemented,
229
230 BufferNotLargeEnough,
232
233 CannotCreateACanonicalMessageWithACapability,
235
236 CannotSetAnyPointerFieldToAPrimitiveValue,
238
239 CantHandleNonStructInlineComposite,
241
242 EmptyBuffer,
244
245 EmptySlice,
247
248 EnumValueOrUnionDiscriminantNotPresent(NotInSchema),
250
251 ExistingListPointerIsNotByteSized,
253
254 ExistingListValueIsIncompatibleWithExpectedType,
256
257 ExistingPointerIsNotAList,
259
260 ExpectedAListOrBlob,
262
263 ExpectedAPointerListButGotAListOfDataOnlyStructs,
265
266 ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs,
268
269 FailedToFillTheWholeBuffer,
271
272 FieldAndDefaultMismatch,
274
275 FieldNotFound,
277
278 FoundBitListWhereStructListWasExpected,
280
281 FoundStructListWhereBitListWasExpected,
283
284 FourByteLengthTooBigForUSize,
286
287 FourByteSegmentLengthTooBigForUSize,
289
290 GroupFieldButTypeIsNotStruct,
292
293 InitIsOnlyValidForStructAndAnyPointerFields,
295
296 InitnIsOnlyValidForListTextOrDataFields,
298
299 InlineCompositeListWithNonStructElementsNotSupported,
301
302 InlineCompositeListsElementsOverrunItsWordCount,
304
305 InlineCompositeListsOfNonStructTypeAreNotSupported,
307
308 InvalidNumberOfSegments(usize),
310
311 InvalidSegmentId(u32),
313
314 ListAnyPointerNotSupported,
316
317 ListCapabilityNotSupported,
319
320 MalformedDoubleFarPointer,
322
323 MessageContainsInvalidCapabilityPointer,
325
326 MessageContainsListPointerOfNonBytesWhereDataWasExpected,
328
329 MessageContainsListPointerOfNonBytesWhereTextWasExpected,
331
332 MessageContainsListWithIncompatibleElementType,
334
335 MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected,
337
338 MessageContainsNonStructPointerWhereStructPointerWasExpected,
340
341 MessageContainsNonListPointerWhereDataWasExpected,
343
344 MessageContainsNonListPointerWhereListPointerWasExpected,
346
347 MessageContainsNonListPointerWhereTextWasExpected,
349
350 MessageContainsNullCapabilityPointer,
352
353 MessageContainsOutOfBoundsPointer,
355
356 MessageContainsTextThatIsNotNULTerminated,
358
359 MessageEndsPrematurely(usize, usize),
361
362 MessageIsTooDeeplyNested,
364
365 MessageIsTooDeeplyNestedOrContainsCycles,
367
368 MessageNotAlignedBy8BytesBoundary,
370
371 MessageSizeOverflow,
373
374 MessageTooLarge(usize),
376
377 NestingLimitExceeded,
379
380 NotAStruct,
382
383 OnlyOneOfTheSectionPointersIsPointingToOurself,
385
386 PackedInputDidNotEndCleanlyOnASegmentBoundary,
388
389 PrematureEndOfFile,
391
392 PrematureEndOfPackedInput,
394
395 ReadLimitExceeded,
397
398 SettingDynamicCapabilitiesIsUnsupported,
400
401 StructReaderHadBitwidthOtherThan1,
403
404 TextBlobMissingNULTerminator,
406
407 TextContainsNonUtf8Data(core::str::Utf8Error),
409
410 TriedToReadFromNullArena,
412
413 TypeMismatch,
415
416 UnalignedSegment,
419
420 UnexpectedFarPointer,
422
423 UnknownPointerType,
425}
426
427impl Error {
428 pub fn write_fmt(&mut self, fmt: core::fmt::Arguments<'_>) {
431 #[cfg(feature = "alloc")]
432 {
433 use core::fmt::Write;
434 let _ = self.extra.write_fmt(fmt);
435 }
436 }
437
438 #[cfg(feature = "alloc")]
439 pub fn failed(description: alloc::string::String) -> Self {
440 Self {
441 extra: description,
442 kind: ErrorKind::Failed,
443 }
444 }
445
446 pub fn from_kind(kind: ErrorKind) -> Self {
447 #[cfg(not(feature = "alloc"))]
448 return Self { kind };
449 #[cfg(feature = "alloc")]
450 return Self {
451 kind,
452 extra: alloc::string::String::new(),
453 };
454 }
455
456 #[cfg(feature = "alloc")]
457 pub fn overloaded(description: alloc::string::String) -> Self {
458 Self {
459 extra: description,
460 kind: ErrorKind::Overloaded,
461 }
462 }
463 #[cfg(feature = "alloc")]
464 pub fn disconnected(description: alloc::string::String) -> Self {
465 Self {
466 extra: description,
467 kind: ErrorKind::Disconnected,
468 }
469 }
470
471 #[cfg(feature = "alloc")]
472 pub fn unimplemented(description: alloc::string::String) -> Self {
473 Self {
474 extra: description,
475 kind: ErrorKind::Unimplemented,
476 }
477 }
478}
479
480#[cfg(feature = "std")]
481impl core::convert::From<::std::io::Error> for Error {
482 fn from(err: ::std::io::Error) -> Self {
483 use std::io;
484 let kind = match err.kind() {
485 io::ErrorKind::TimedOut => ErrorKind::Overloaded,
486 io::ErrorKind::BrokenPipe
487 | io::ErrorKind::ConnectionRefused
488 | io::ErrorKind::ConnectionReset
489 | io::ErrorKind::ConnectionAborted
490 | io::ErrorKind::NotConnected => ErrorKind::Disconnected,
491 io::ErrorKind::UnexpectedEof => ErrorKind::PrematureEndOfFile,
492 _ => ErrorKind::Failed,
493 };
494 #[cfg(feature = "alloc")]
495 return Self {
496 kind,
497 extra: format!("{err}"),
498 };
499 #[cfg(not(feature = "alloc"))]
500 return Self { kind };
501 }
502}
503
504#[cfg(feature = "embedded-io")]
505impl From<embedded_io::ErrorKind> for ErrorKind {
506 fn from(value: embedded_io::ErrorKind) -> Self {
507 match value {
508 embedded_io::ErrorKind::Other => Self::Failed,
509 embedded_io::ErrorKind::NotFound => Self::Failed,
510 embedded_io::ErrorKind::PermissionDenied => Self::Failed,
511 embedded_io::ErrorKind::ConnectionRefused => Self::Failed,
512 embedded_io::ErrorKind::ConnectionReset => Self::Failed,
513 embedded_io::ErrorKind::ConnectionAborted => Self::Failed,
514 embedded_io::ErrorKind::NotConnected => Self::Failed,
515 embedded_io::ErrorKind::AddrInUse => Self::Failed,
516 embedded_io::ErrorKind::AddrNotAvailable => Self::Failed,
517 embedded_io::ErrorKind::BrokenPipe => Self::Failed,
518 embedded_io::ErrorKind::AlreadyExists => Self::Failed,
519 embedded_io::ErrorKind::InvalidInput => Self::Failed,
520 embedded_io::ErrorKind::InvalidData => Self::Failed,
521 embedded_io::ErrorKind::TimedOut => Self::Failed,
522 embedded_io::ErrorKind::Interrupted => Self::Failed,
523 embedded_io::ErrorKind::Unsupported => Self::Failed,
524 embedded_io::ErrorKind::OutOfMemory => Self::Failed,
525 _ => Self::Failed,
526 }
527 }
528}
529
530#[cfg(feature = "alloc")]
531impl core::convert::From<alloc::string::FromUtf8Error> for Error {
532 fn from(err: alloc::string::FromUtf8Error) -> Self {
533 Self::failed(format!("{err}"))
534 }
535}
536
537impl core::convert::From<core::str::Utf8Error> for Error {
538 fn from(err: core::str::Utf8Error) -> Self {
539 Self::from_kind(ErrorKind::TextContainsNonUtf8Data(err))
540 }
541}
542
543impl core::convert::From<NotInSchema> for Error {
544 fn from(e: NotInSchema) -> Self {
545 Self::from_kind(ErrorKind::EnumValueOrUnionDiscriminantNotPresent(e))
546 }
547}
548
549impl core::fmt::Display for ErrorKind {
550 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
551 match self {
552 Self::Failed => write!(fmt, "Failed"),
553 Self::Overloaded => write!(fmt, "Overloaded"),
554 Self::Disconnected => write!(fmt, "Disconnected"),
555 Self::Unimplemented => write!(fmt, "Unimplemented"),
556 Self::BufferNotLargeEnough => write!(fmt, "buffer is not large enough"),
557 Self::ExistingListPointerIsNotByteSized => write!(fmt, "Called get_writable_{{data|text}}_pointer() but existing list pointer is not byte-sized."),
558 Self::ExistingPointerIsNotAList => write!(fmt, "Called get_writable_{{data|text|list|struct_list}}_pointer() but existing pointer is not a list."),
559 Self::CannotCreateACanonicalMessageWithACapability => write!(fmt, "Cannot create a canonical message with a capability"),
560 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."),
561 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"),
562 Self::CannotSetAnyPointerFieldToAPrimitiveValue => write!(fmt, "cannot set AnyPointer field to a primitive value"),
563 Self::CantHandleNonStructInlineComposite => write!(fmt, "Don't know how to handle non-STRUCT inline composite."),
564 Self::EmptyBuffer => write!(fmt, "empty buffer"),
565 Self::EmptySlice => write!(fmt, "empty slice"),
566 Self::EnumValueOrUnionDiscriminantNotPresent(val) => write!(fmt, "Enum value or union discriminant {val} was not present in schema"),
567 Self::ExistingListValueIsIncompatibleWithExpectedType => write!(fmt, "Existing list value is incompatible with expected type."),
568 Self::ExpectedAListOrBlob => write!(fmt, "Expected a list or blob."),
569 Self::ExpectedAPointerListButGotAListOfDataOnlyStructs => write!(fmt, "Expected a pointer list, but got a list of data-only structs"),
570 Self::ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs => write!(fmt, "Expected a primitive list, but got a list of pointer-only structs"),
571 Self::FailedToFillTheWholeBuffer => write!(fmt, "failed to fill the whole buffer"),
572 Self::FieldAndDefaultMismatch => write!(fmt, "field and default mismatch"),
573 Self::FieldNotFound => write!(fmt, "field not found"),
574 Self::FoundBitListWhereStructListWasExpected => write!(fmt, "Found bit list where struct list was expected; upgrading boolean lists to struct lists is no longer supported."),
575 Self::FoundStructListWhereBitListWasExpected => write!(fmt, "Found struct list where bit list was expected."),
576 Self::GroupFieldButTypeIsNotStruct => write!(fmt, "group field but type is not Struct"),
577 Self::InitIsOnlyValidForStructAndAnyPointerFields => write!(fmt, "init() is only valid for struct and AnyPointer fields"),
578 Self::InitnIsOnlyValidForListTextOrDataFields => write!(fmt, "initn() is only valid for list, text, or data fields"),
579 Self::InlineCompositeListWithNonStructElementsNotSupported => write!(fmt, "InlineComposite list with non-STRUCT elements not supported."),
580 Self::InlineCompositeListsElementsOverrunItsWordCount => write!(fmt, "InlineComposite list's elements overrun its word count."),
581 Self::InlineCompositeListsOfNonStructTypeAreNotSupported => write!(fmt, "InlineComposite lists of non-STRUCT type are not supported."),
582 Self::InvalidNumberOfSegments(segment_count) => write!(fmt, "Too many or too few segments {segment_count}"),
583 Self::InvalidSegmentId(id) => write!(fmt, "Invalid segment id {id}"),
584 Self::ListAnyPointerNotSupported => write!(fmt, "List(AnyPointer) not supported."),
585 Self::ListCapabilityNotSupported => write!(fmt, "List(Capability) not supported"),
586 Self::MalformedDoubleFarPointer => write!(fmt, "Malformed double-far pointer."),
587 Self::MessageContainsInvalidCapabilityPointer => write!(fmt, "Message contained invalid capability pointer."),
588 Self::MessageContainsListPointerOfNonBytesWhereDataWasExpected => write!(fmt, "Message contains list pointer of non-bytes where data was expected."),
589 Self::MessageContainsListPointerOfNonBytesWhereTextWasExpected => write!(fmt, "Message contains list pointer of non-bytes where text was expected."),
590 Self::MessageContainsListWithIncompatibleElementType => write!(fmt, "Message contains list with incompatible element type."),
591 Self::MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected => write!(fmt, "Message contains non-capability pointer where capability pointer was expected."),
592 Self::MessageContainsNonListPointerWhereDataWasExpected => write!(fmt, "Message contains non-list pointer where data was expected."),
593 Self::MessageContainsNonListPointerWhereListPointerWasExpected => write!(fmt, "Message contains non-list pointer where list pointer was expected"),
594 Self::MessageContainsNonListPointerWhereTextWasExpected => write!(fmt, "Message contains non-list pointer where text was expected."),
595 Self::MessageContainsNonStructPointerWhereStructPointerWasExpected => write!(fmt, "Message contains non-struct pointer where struct pointer was expected."),
596 Self::MessageContainsNullCapabilityPointer => write!(fmt, "Message contains null capability pointer."),
597 Self::MessageContainsOutOfBoundsPointer => write!(fmt, "Message contains out-of-bounds pointer"),
598 Self::MessageContainsTextThatIsNotNULTerminated => write!(fmt, "Message contains text that is not NUL-terminated"),
599 Self::MessageEndsPrematurely(header, body) => write!(fmt, "Message ends prematurely. Header claimed {header} words, but message only has {body} words"),
600 Self::MessageIsTooDeeplyNested => write!(fmt, "Message is too deeply nested."),
601 Self::MessageIsTooDeeplyNestedOrContainsCycles => write!(fmt, "Message is too deeply-nested or contains cycles."),
602 Self::MessageSizeOverflow => write!(fmt, "Message's size cannot be represented in usize"),
603 Self::MessageTooLarge(val) => write!(fmt, "Message is too large: {val}"),
604 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."),
605 Self::NestingLimitExceeded => write!(fmt, "nesting limit exceeded"),
606 Self::NotAStruct => write!(fmt, "not a struct"),
607 Self::OnlyOneOfTheSectionPointersIsPointingToOurself => write!(fmt, "Only one of the section pointers is pointing to ourself"),
608 Self::PackedInputDidNotEndCleanlyOnASegmentBoundary => write!(fmt, "Packed input did not end cleanly on a segment boundary."),
609 Self::PrematureEndOfFile => write!(fmt, "Premature end of file"),
610 Self::PrematureEndOfPackedInput => write!(fmt, "Premature end of packed input."),
611 Self::ReadLimitExceeded => write!(fmt, "Read limit exceeded"),
612 Self::SettingDynamicCapabilitiesIsUnsupported => write!(fmt, "setting dynamic capabilities is unsupported"),
613 Self::StructReaderHadBitwidthOtherThan1 => write!(fmt, "struct reader had bitwidth other than 1"),
614 Self::TextBlobMissingNULTerminator => write!(fmt, "Text blob missing NUL terminator."),
615 Self::TextContainsNonUtf8Data(e) => write!(fmt, "Text contains non-utf8 data: {e}"),
616 Self::TriedToReadFromNullArena => write!(fmt, "Tried to read from null arena"),
617 Self::TypeMismatch => write!(fmt, "type mismatch"),
618 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"),
619 Self::UnexpectedFarPointer => write!(fmt, "Unexpected far pointer"),
620 Self::UnknownPointerType => write!(fmt, "Unknown pointer type."),
621 }
622 }
623}
624
625impl core::fmt::Display for Error {
626 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
627 #[cfg(feature = "alloc")]
628 let result = if self.extra.is_empty() {
629 write!(fmt, "{}", self.kind)
630 } else {
631 write!(fmt, "{}: {}", self.kind, self.extra)
632 };
633 #[cfg(not(feature = "alloc"))]
634 let result = write!(fmt, "{}", self.kind);
635 result
636 }
637}
638
639impl core::error::Error for Error {
640 #[cfg(feature = "alloc")]
641 fn description(&self) -> &str {
642 &self.extra
643 }
644 fn cause(&self) -> Option<&dyn ::core::error::Error> {
645 None
646 }
647}
648
649pub enum OutputSegments<'a> {
652 SingleSegment([&'a [u8]; 1]),
653
654 #[cfg(feature = "alloc")]
655 MultiSegment(alloc::vec::Vec<&'a [u8]>),
656}
657
658impl<'a> core::ops::Deref for OutputSegments<'a> {
659 type Target = [&'a [u8]];
660 fn deref(&self) -> &[&'a [u8]] {
661 match self {
662 OutputSegments::SingleSegment(s) => s,
663
664 #[cfg(feature = "alloc")]
665 OutputSegments::MultiSegment(v) => v,
666 }
667 }
668}
669
670impl message::ReaderSegments for OutputSegments<'_> {
671 fn get_segment(&self, id: u32) -> Option<&[u8]> {
672 match self {
673 OutputSegments::SingleSegment(s) => s.get(id as usize).copied(),
674
675 #[cfg(feature = "alloc")]
676 OutputSegments::MultiSegment(v) => v.get(id as usize).copied(),
677 }
678 }
679}