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