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}