pw_status/
pw_status.rs

1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15//! # pw_status
16//!
17//! Rust error types using error codes compatible with Pigweed's
18//! [pw_status](https://pigweed.dev/pw_status).  In order to keep the interface
19//! idiomatic for Rust, `PW_STATUS_OK` is omitted from the Error enum and a
20//! `StatusCode` trait is provided to turn a `Result` into a canonical
21//! status code.
22//!
23//! For an in depth explanation of the values of the `Error` enum, see
24//! the [Pigweed status codes documentation](https://pigweed.dev/pw_status/#status-codes).
25//!
26//! # Example
27//!
28//! ```
29//! use pw_status::{Error, Result};
30//!
31//! fn div(numerator: u32, denominator: u32) -> Result<u32> {
32//!     if denominator == 0 {
33//!         Err(Error::FailedPrecondition)
34//!     } else {
35//!         Ok(numerator / denominator)
36//!     }
37//! }
38//!
39//! assert_eq!(div(4, 2), Ok(2));
40//! assert_eq!(div(4, 0), Err(Error::FailedPrecondition));
41//! ```
42
43#![cfg_attr(not(feature = "std"), no_std)]
44
45/// Status code for no error.
46pub const OK: u32 = 0;
47
48#[cfg_attr(feature = "std", derive(Debug))]
49#[derive(Clone, Copy, Eq, PartialEq)]
50/// Error type compatible with Pigweed's [pw_status](https://pigweed.dev/pw_status).
51///
52/// For an in depth explanation of the values of the `Error` enum, see
53/// the [Pigweed status codes documentation](https://pigweed.dev/pw_status/#status-codes).
54pub enum Error {
55    Cancelled = 1,
56    Unknown = 2,
57    InvalidArgument = 3,
58    DeadlineExceeded = 4,
59    NotFound = 5,
60    AlreadyExists = 6,
61    PermissionDenied = 7,
62    ResourceExhausted = 8,
63    FailedPrecondition = 9,
64    Aborted = 10,
65    OutOfRange = 11,
66    Unimplemented = 12,
67    Internal = 13,
68    Unavailable = 14,
69    DataLoss = 15,
70    Unauthenticated = 16,
71}
72
73pub type Result<T> = core::result::Result<T, Error>;
74
75/// Convert a Result into an status code.
76pub trait StatusCode {
77    /// Return a pigweed compatible status code.
78    fn status_code(self) -> u32;
79}
80
81impl<T> StatusCode for Result<T> {
82    fn status_code(self) -> u32 {
83        match self {
84            Ok(_) => OK,
85            Err(e) => e as u32,
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    #[test]
94    fn test_status_code() {
95        assert_eq!(Result::Ok(()).status_code(), 0);
96        assert_eq!(Result::<()>::Err(Error::Cancelled).status_code(), 1);
97        assert_eq!(Result::<()>::Err(Error::Unknown).status_code(), 2);
98        assert_eq!(Result::<()>::Err(Error::InvalidArgument).status_code(), 3);
99        assert_eq!(Result::<()>::Err(Error::DeadlineExceeded).status_code(), 4);
100        assert_eq!(Result::<()>::Err(Error::NotFound).status_code(), 5);
101        assert_eq!(Result::<()>::Err(Error::AlreadyExists).status_code(), 6);
102        assert_eq!(Result::<()>::Err(Error::PermissionDenied).status_code(), 7);
103        assert_eq!(Result::<()>::Err(Error::ResourceExhausted).status_code(), 8);
104        assert_eq!(
105            Result::<()>::Err(Error::FailedPrecondition).status_code(),
106            9
107        );
108        assert_eq!(Result::<()>::Err(Error::Aborted).status_code(), 10);
109        assert_eq!(Result::<()>::Err(Error::OutOfRange).status_code(), 11);
110        assert_eq!(Result::<()>::Err(Error::Unimplemented).status_code(), 12);
111        assert_eq!(Result::<()>::Err(Error::Internal).status_code(), 13);
112        assert_eq!(Result::<()>::Err(Error::Unavailable).status_code(), 14);
113        assert_eq!(Result::<()>::Err(Error::DataLoss).status_code(), 15);
114        assert_eq!(Result::<()>::Err(Error::Unauthenticated).status_code(), 16);
115    }
116}