Skip to content

Commit 81cdb73

Browse files
Start to add error types at cel and property level
Signed-off-by: Adam Cattermole <[email protected]>
1 parent 59abc4f commit 81cdb73

File tree

5 files changed

+282
-117
lines changed

5 files changed

+282
-117
lines changed

src/auth_action.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ impl AuthAction {
3535
}
3636

3737
pub fn conditions_apply(&self) -> bool {
38-
self.predicates.apply()
38+
//todo(adam-cattermole): do not expect
39+
self.predicates.apply().expect("REMOVE")
3940
}
4041

4142
pub fn get_failure_mode(&self) -> FailureMode {

src/data/attribute.rs

+126-62
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,184 @@
1-
use crate::data::PropertyPath;
1+
use crate::data::attribute::errors::PropError;
2+
use crate::data::{PropertyError, PropertyPath};
23
use chrono::{DateTime, FixedOffset};
34
use log::{debug, error, warn};
45
use protobuf::well_known_types::Struct;
56
use serde_json::Value;
67

78
pub const KUADRANT_NAMESPACE: &str = "kuadrant";
89

10+
pub(super) mod errors {
11+
use std::error::Error;
12+
use std::fmt::{Debug, Display, Formatter};
13+
14+
#[derive(PartialEq)]
15+
pub enum PropertyError {
16+
GetPropertyError(PropError),
17+
ParsePropertyError(PropError),
18+
}
19+
20+
impl Error for PropertyError {
21+
fn source(&self) -> Option<&(dyn Error + 'static)> {
22+
match self {
23+
PropertyError::GetPropertyError(err) => Some(err),
24+
PropertyError::ParsePropertyError(err) => Some(err),
25+
}
26+
}
27+
}
28+
29+
impl Display for PropertyError {
30+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31+
match self {
32+
PropertyError::GetPropertyError(e) => {
33+
write!(f, "PropertyError::GetPropertyError {{ {} }}", e)
34+
}
35+
PropertyError::ParsePropertyError(e) => {
36+
write!(f, "PropertyError::ParsePropertyError {{ {} }}", e)
37+
}
38+
}
39+
}
40+
}
41+
42+
impl Debug for PropertyError {
43+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44+
write!(f, "{}", self)
45+
}
46+
}
47+
48+
#[derive(PartialEq)]
49+
pub struct PropError {
50+
message: String,
51+
}
52+
53+
impl Display for PropError {
54+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55+
write!(f, "PropError {{ message: {} }}", self.message)
56+
}
57+
}
58+
59+
impl Debug for PropError {
60+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61+
write!(f, "{}", self)
62+
}
63+
}
64+
65+
impl Error for PropError {}
66+
67+
impl PropError {
68+
pub fn new(message: String) -> PropError {
69+
PropError { message }
70+
}
71+
}
72+
}
73+
974
pub trait AttributeValue {
10-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String>
75+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError>
1176
where
1277
Self: Sized;
1378
}
1479

1580
impl AttributeValue for String {
16-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
81+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
1782
String::from_utf8(raw_attribute).map_err(|err| {
18-
format!(
83+
PropError::new(format!(
1984
"parse: failed to parse selector String value, error: {}",
2085
err
21-
)
86+
))
2287
})
2388
}
2489
}
2590

2691
impl AttributeValue for i64 {
27-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
28-
if raw_attribute.len() != 8 {
29-
return Err(format!(
30-
"parse: Int value expected to be 8 bytes, but got {}",
31-
raw_attribute.len()
32-
));
92+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
93+
let bytes: Result<[u8; 8], _> = raw_attribute[..8].try_into();
94+
if bytes.is_ok() && raw_attribute.len() == 8 {
95+
if let Ok(bytes) = bytes {
96+
return Ok(i64::from_le_bytes(bytes));
97+
}
3398
}
34-
Ok(i64::from_le_bytes(
35-
raw_attribute[..8]
36-
.try_into()
37-
.expect("This has to be 8 bytes long!"),
38-
))
99+
Err(PropError::new(format!(
100+
"parse: Int value expected to be 8 bytes, but got {}",
101+
raw_attribute.len()
102+
)))
39103
}
40104
}
41105

42106
impl AttributeValue for u64 {
43-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
44-
if raw_attribute.len() != 8 {
45-
return Err(format!(
46-
"parse: UInt value expected to be 8 bytes, but got {}",
47-
raw_attribute.len()
48-
));
107+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
108+
let bytes: Result<[u8; 8], _> = raw_attribute[..8].try_into();
109+
if bytes.is_ok() && raw_attribute.len() == 8 {
110+
if let Ok(bytes) = bytes {
111+
return Ok(u64::from_le_bytes(bytes));
112+
}
49113
}
50-
Ok(u64::from_le_bytes(
51-
raw_attribute[..8]
52-
.try_into()
53-
.expect("This has to be 8 bytes long!"),
54-
))
114+
Err(PropError::new(format!(
115+
"parse: UInt value expected to be 8 bytes, but got {}",
116+
raw_attribute.len()
117+
)))
55118
}
56119
}
57120

58121
impl AttributeValue for f64 {
59-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
60-
if raw_attribute.len() != 8 {
61-
return Err(format!(
62-
"parse: Float value expected to be 8 bytes, but got {}",
63-
raw_attribute.len()
64-
));
122+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
123+
let bytes: Result<[u8; 8], _> = raw_attribute[..8].try_into();
124+
if bytes.is_ok() && raw_attribute.len() == 8 {
125+
if let Ok(bytes) = bytes {
126+
return Ok(f64::from_le_bytes(bytes));
127+
}
65128
}
66-
Ok(f64::from_le_bytes(
67-
raw_attribute[..8]
68-
.try_into()
69-
.expect("This has to be 8 bytes long!"),
70-
))
129+
Err(PropError::new(format!(
130+
"parse: Float value expected to be 8 bytes, but got {}",
131+
raw_attribute.len()
132+
)))
71133
}
72134
}
73135

74136
impl AttributeValue for Vec<u8> {
75-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
137+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
76138
Ok(raw_attribute)
77139
}
78140
}
79141

80142
impl AttributeValue for bool {
81-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
82-
if raw_attribute.len() != 1 {
83-
return Err(format!(
84-
"parse: Bool value expected to be 1 byte, but got {}",
85-
raw_attribute.len()
86-
));
143+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
144+
if raw_attribute.len() == 1 {
145+
return Ok(raw_attribute[0] & 1 == 1);
87146
}
88-
Ok(raw_attribute[0] & 1 == 1)
147+
Err(PropError::new(format!(
148+
"parse: Bool value expected to be 1 byte, but got {}",
149+
raw_attribute.len()
150+
)))
89151
}
90152
}
91153

92154
impl AttributeValue for DateTime<FixedOffset> {
93-
fn parse(raw_attribute: Vec<u8>) -> Result<Self, String> {
94-
if raw_attribute.len() != 8 {
95-
return Err(format!(
96-
"parse: Timestamp expected to be 8 bytes, but got {}",
97-
raw_attribute.len()
98-
));
155+
fn parse(raw_attribute: Vec<u8>) -> Result<Self, PropError> {
156+
let bytes: Result<[u8; 8], _> = raw_attribute[..8].try_into();
157+
if bytes.is_ok() && raw_attribute.len() == 8 {
158+
if let Ok(bytes) = bytes {
159+
let nanos = i64::from_le_bytes(bytes);
160+
return Ok(DateTime::from_timestamp_nanos(nanos).into());
161+
}
99162
}
100-
101-
let nanos = i64::from_le_bytes(
102-
raw_attribute.as_slice()[..8]
103-
.try_into()
104-
.expect("This has to be 8 bytes long!"),
105-
);
106-
Ok(DateTime::from_timestamp_nanos(nanos).into())
163+
Err(PropError::new(format!(
164+
"parse: Timestamp expected to be 8 bytes, but got {}",
165+
raw_attribute.len()
166+
)))
107167
}
108168
}
109169

110-
pub fn get_attribute<T>(path: &PropertyPath) -> Result<Option<T>, String>
170+
pub fn get_attribute<T>(path: &PropertyPath) -> Result<Option<T>, PropertyError>
111171
where
112172
T: AttributeValue,
113173
{
114174
match crate::data::property::get_property(path) {
115-
Ok(Some(attribute_bytes)) => Ok(Some(T::parse(attribute_bytes)?)),
175+
Ok(Some(attribute_bytes)) => Ok(Some(
176+
T::parse(attribute_bytes).map_err(PropertyError::ParsePropertyError)?,
177+
)),
116178
Ok(None) => Ok(None),
117-
Err(e) => Err(format!("get_attribute: error: {e:?}")),
179+
Err(e) => Err(PropertyError::GetPropertyError(PropError::new(format!(
180+
"get_attribute: error: {e:?}"
181+
)))),
118182
}
119183
}
120184

0 commit comments

Comments
 (0)