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