@@ -12,78 +12,58 @@ use core::fmt;
12
12
use core:: num:: NonZeroU32 ;
13
13
14
14
15
- // A randomly-chosen 24-bit prefix for our codes.
16
- #[ cfg( not( feature="std" ) ) ]
17
- pub ( crate ) const CODE_PREFIX : u32 = 0x517e8100 ;
18
-
19
15
/// Error type of random number generators
20
- ///
21
- /// This is a relatively simple error type, designed for compatibility with and
22
- /// without the Rust `std` library. It embeds a message (static
23
- /// string only), and an optional chained cause (`std` only). The
24
- /// `msg` field can be accessed directly; cause can be accessed via
25
- /// `std::error::Error::cause` or `Error::take_cause`. Construction can only be
26
- /// done via `Error::new` or `Error::with_cause`.
16
+ ///
17
+ /// In order to be compatible with `std` and `no_std`, this type has two
18
+ /// possible implementations: with `std` a boxed `Error` trait object is stored,
19
+ /// while with `no_std` we merely store an error code.
27
20
#[ derive( Debug ) ]
28
21
pub struct Error {
29
- msg : & ' static str ,
30
22
#[ cfg( feature="std" ) ]
31
- cause : Option < Box < std:: error:: Error + Send + Sync > > ,
23
+ inner : Box < dyn std:: error:: Error + Send + Sync + ' static > ,
32
24
#[ cfg( not( feature="std" ) ) ]
33
25
code : NonZeroU32 ,
34
26
}
35
27
36
28
impl Error {
37
- /// Create a new instance, with a message.
38
- pub fn new ( msg : & ' static str ) -> Self {
39
- #[ cfg( feature="std" ) ] {
40
- Error { msg, cause : None }
41
- }
42
- #[ cfg( not( feature="std" ) ) ] {
43
- Error { msg, code : NonZeroU32 :: new ( CODE_PREFIX ) . unwrap ( ) }
44
- }
45
- }
46
-
47
- /// Create a new instance, with a message and a chained cause.
48
- ///
49
- /// This function is only available with the `std` feature.
50
- // NOTE: with specialisation we could support both.
29
+ /// Construct from any type supporting `std::error::Error`
30
+ ///
31
+ /// Available only when configured with `std`.
32
+ ///
33
+ /// See also `From<NonZeroU32>`, which is available with and without `std`.
51
34
#[ cfg( feature="std" ) ]
52
- pub fn with_cause < E > ( msg : & ' static str , cause : E ) -> Self
53
- where E : Into < Box < std:: error:: Error + Send + Sync > >
35
+ pub fn new < E > ( err : E ) -> Self
36
+ where E : Into < Box < dyn std:: error:: Error + Send + Sync + ' static > >
54
37
{
55
- Error { msg , cause : Some ( cause . into ( ) ) }
38
+ Error { inner : err . into ( ) }
56
39
}
57
40
58
- /// Create a new instance, with a message and an error code.
59
- pub fn with_code ( msg : & ' static str , code : NonZeroU32 ) -> Self {
60
- #[ cfg( feature="std" ) ] {
61
- Error { msg, cause : Some ( Box :: new ( ErrorCode ( code) ) ) }
62
- }
63
- #[ cfg( not( feature="std" ) ) ] {
64
- Error { msg, code }
65
- }
66
- }
67
-
68
- /// Retrieve the error message.
69
- pub fn msg ( & self ) -> & str {
70
- self . msg
41
+ /// Reference the inner error (`std` only)
42
+ ///
43
+ /// When configured with `std`, this is a trivial operation and never
44
+ /// panics. Without `std`, this method is simply unavailable.
45
+ #[ cfg( feature="std" ) ]
46
+ pub fn inner ( & self ) -> & ( dyn std:: error:: Error + Send + Sync + ' static ) {
47
+ & * self . inner
71
48
}
72
49
73
- /// Take the cause, if any. This allows the embedded cause to be extracted.
74
- /// This uses `Option::take`, leaving `self` with no cause.
75
- ///
76
- /// This function is only available with the `std` feature .
50
+ /// Unwrap the inner error (`std` only)
51
+ ///
52
+ /// When configured with `std`, this is a trivial operation and never
53
+ /// panics. Without `std`, this method is simply unavailable .
77
54
#[ cfg( feature="std" ) ]
78
- pub fn take_cause ( & mut self ) -> Option < Box < std:: error:: Error + Send + Sync > > {
79
- self . cause . take ( )
55
+ pub fn take_inner ( self ) -> Box < dyn std:: error:: Error + Send + Sync + ' static > {
56
+ self . inner
80
57
}
81
58
82
59
/// Retrieve the error code, if any.
83
- #[ cfg( not( feature="std" ) ) ]
60
+ ///
61
+ /// If this `Error` was constructed via `From<NonZeroU32>`, then this method
62
+ /// will return this `NonZeroU32` code (for `no_std` this is always the
63
+ /// case). Otherwise, this method will return `None`.
84
64
pub fn code ( & self ) -> Option < NonZeroU32 > {
85
65
#[ cfg( feature="std" ) ] {
86
- self . cause . as_ref ( ) . and_then ( |b| b . downcast_ref :: < ErrorCode > ( ) ) . map ( |c| c. 0 )
66
+ self . inner . downcast_ref :: < ErrorCode > ( ) . map ( |c| c. 0 )
87
67
}
88
68
#[ cfg( not( feature="std" ) ) ] {
89
69
Some ( self . code )
@@ -93,31 +73,42 @@ impl Error {
93
73
94
74
impl fmt:: Display for Error {
95
75
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
96
- write ! ( f, "{}" , self . msg)
76
+ #[ cfg( feature="std" ) ] {
77
+ write ! ( f, "{}" , self . inner)
78
+ }
79
+ #[ cfg( not( feature="std" ) ) ] {
80
+ write ! ( f, "error code {}" , self . code)
81
+ }
82
+ }
83
+ }
84
+
85
+ impl From < NonZeroU32 > for Error {
86
+ fn from ( code : NonZeroU32 ) -> Self {
87
+ #[ cfg( feature="std" ) ] {
88
+ Error { inner : Box :: new ( ErrorCode ( code) ) }
89
+ }
90
+ #[ cfg( not( feature="std" ) ) ] {
91
+ Error { code }
92
+ }
97
93
}
98
94
}
99
95
100
96
#[ cfg( feature="getrandom" ) ]
101
97
impl From < getrandom:: Error > for Error {
102
98
fn from ( error : getrandom:: Error ) -> Self {
103
- let msg = "getrandom error" ;
104
99
#[ cfg( feature="std" ) ] {
105
- Error { msg , cause : Some ( Box :: new ( error) ) }
100
+ Error { inner : Box :: new ( error) }
106
101
}
107
102
#[ cfg( not( feature="std" ) ) ] {
108
- Error { msg , code : error. code ( ) }
103
+ Error { code : error. code ( ) }
109
104
}
110
105
}
111
106
}
112
107
113
108
#[ cfg( feature="std" ) ]
114
109
impl std:: error:: Error for Error {
115
- fn description ( & self ) -> & str {
116
- self . msg
117
- }
118
-
119
110
fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
120
- self . cause . as_ref ( ) . map ( |e| e . as_ref ( ) as & std :: error :: Error )
111
+ self . inner . source ( )
121
112
}
122
113
}
123
114
@@ -135,7 +126,7 @@ struct ErrorCode(NonZeroU32);
135
126
#[ cfg( feature="std" ) ]
136
127
impl fmt:: Display for ErrorCode {
137
128
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
138
- write ! ( f, "ErrorCode({}) " , self . 0 )
129
+ write ! ( f, "error code {} " , self . 0 )
139
130
}
140
131
}
141
132
0 commit comments