Skip to main content

concinnity_core/
result.rs

1//! The engine's flat result code, shared by every crate that reports a
2//! recoverable failure across an API or FFI seam.
3
4use thiserror::Error;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
7#[non_exhaustive]
8/// The engine's flat result code, returned across the API and FFI seams.
9pub enum CnResult {
10    #[error("Success")]
11    /// The call succeeded.
12    Success = 0,
13
14    #[error("Invalid asset type")]
15    /// The asset type name is not in the registry.
16    AssetInvalidType,
17
18    /// Generic
19    #[error("Invalid state")]
20    InvalidState,
21    #[error("Invalid argument")]
22    /// An argument was outside its accepted range.
23    InvalidArgument,
24
25    #[error("File I/O error")]
26    /// A file could not be read or written.
27    FileIo,
28
29    #[error("No state directory installed")]
30    /// Project state was read by a caller that was handed no state tree. See
31    /// `concinnity_host::store::paths::StateTree`.
32    NoStateRoot,
33}
34
35// Baking a component into its blob record serializes it with postcard.
36impl From<postcard::Error> for CnResult {
37    fn from(_: postcard::Error) -> Self {
38        CnResult::InvalidArgument
39    }
40}
41
42// Reading one back reads a length-delimited frame; a failure means the record
43// and the component schema disagree (a stale blob survives the version check
44// instead of reaching here).
45impl From<crate::blob::FrameError> for CnResult {
46    fn from(_: crate::blob::FrameError) -> Self {
47        CnResult::InvalidArgument
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use alloc::string::{String, ToString};
55
56    #[test]
57    fn display_messages_are_stable() {
58        assert_eq!(CnResult::Success.to_string(), "Success");
59        assert_eq!(CnResult::AssetInvalidType.to_string(), "Invalid asset type");
60        assert_eq!(CnResult::InvalidState.to_string(), "Invalid state");
61        assert_eq!(CnResult::InvalidArgument.to_string(), "Invalid argument");
62        assert_eq!(CnResult::FileIo.to_string(), "File I/O error");
63        assert_eq!(
64            CnResult::NoStateRoot.to_string(),
65            "No state directory installed"
66        );
67    }
68
69    #[test]
70    fn frame_errors_map_to_invalid_argument() {
71        let bad = crate::blob::decode_exact::<String>(&[0xff]).unwrap_err();
72        assert_eq!(CnResult::from(bad), CnResult::InvalidArgument);
73
74        let trailing = crate::blob::decode_exact::<u8>(&[1, 2]).unwrap_err();
75        assert_eq!(CnResult::from(trailing), CnResult::InvalidArgument);
76    }
77}