From 58e51f4f4748e5cff3102487583237c608af8985 Mon Sep 17 00:00:00 2001 From: davidemazzocchi Date: Fri, 17 Oct 2025 09:03:21 +0200 Subject: [PATCH] review: change trait req for entity unwrap* functions to TryFrom to handle errors --- 01.workspace/heave/examples/simple_product.rs | 6 +- 01.workspace/heave/src/imp/bool_from_value.rs | 10 --- .../heave/src/imp/bool_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/f64_from_value.rs | 10 --- .../heave/src/imp/f64_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/i32_from_value.rs | 13 ---- .../heave/src/imp/i32_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/i64_from_value.rs | 10 --- .../heave/src/imp/i64_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/mod.rs | 14 ++-- .../heave/src/imp/string_from_value.rs | 10 --- .../heave/src/imp/string_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/u32_from_value.rs | 13 ---- .../heave/src/imp/u32_try_from_value.rs | 11 +++ 01.workspace/heave/src/imp/u64_from_value.rs | 10 --- .../heave/src/imp/u64_try_from_value.rs | 11 +++ 01.workspace/heave/src/str/catalog.rs | 8 ++- 01.workspace/heave/src/str/entity.rs | 67 +++++++++++-------- 01.workspace/heave/src/str/failed_to.rs | 2 + 19 files changed, 132 insertions(+), 118 deletions(-) delete mode 100644 01.workspace/heave/src/imp/bool_from_value.rs create mode 100644 01.workspace/heave/src/imp/bool_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/f64_from_value.rs create mode 100644 01.workspace/heave/src/imp/f64_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/i32_from_value.rs create mode 100644 01.workspace/heave/src/imp/i32_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/i64_from_value.rs create mode 100644 01.workspace/heave/src/imp/i64_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/string_from_value.rs create mode 100644 01.workspace/heave/src/imp/string_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/u32_from_value.rs create mode 100644 01.workspace/heave/src/imp/u32_try_from_value.rs delete mode 100644 01.workspace/heave/src/imp/u64_from_value.rs create mode 100644 01.workspace/heave/src/imp/u64_try_from_value.rs diff --git a/01.workspace/heave/examples/simple_product.rs b/01.workspace/heave/examples/simple_product.rs index 071c267..10ceb49 100644 --- a/01.workspace/heave/examples/simple_product.rs +++ b/01.workspace/heave/examples/simple_product.rs @@ -46,11 +46,11 @@ impl From for Product { // Set the product's ID from the entity's ID. id: value.id.clone(), // Unwrap the "name" attribute to get the product's name. - name: value.unwrap("name"), + name: value.unwrap("name").expect("name is always present"), // Unwrap the optional "model" attribute to get the product's model. - model: value.unwrap_opt("model"), + model: value.unwrap_opt("model").expect("model is always present"), // Unwrap the "price" attribute to get the product's price. - price: value.unwrap("price"), + price: value.unwrap("price").expect("price is always present"), } } } diff --git a/01.workspace/heave/src/imp/bool_from_value.rs b/01.workspace/heave/src/imp/bool_from_value.rs deleted file mode 100644 index f73ff06..0000000 --- a/01.workspace/heave/src/imp/bool_from_value.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::*; - -impl From for bool { - fn from(value: Value) -> bool { - match value { - Value::Bool(value) => value, - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/bool_try_from_value.rs b/01.workspace/heave/src/imp/bool_try_from_value.rs new file mode 100644 index 0000000..30f5e0a --- /dev/null +++ b/01.workspace/heave/src/imp/bool_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for bool { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::Bool(value) => Ok(value), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/f64_from_value.rs b/01.workspace/heave/src/imp/f64_from_value.rs deleted file mode 100644 index 7b5d9e2..0000000 --- a/01.workspace/heave/src/imp/f64_from_value.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::*; - -impl From for f64 { - fn from(value: Value) -> f64 { - match value { - Value::Real(value) => value, - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/f64_try_from_value.rs b/01.workspace/heave/src/imp/f64_try_from_value.rs new file mode 100644 index 0000000..72b4305 --- /dev/null +++ b/01.workspace/heave/src/imp/f64_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for f64 { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::Real(value) => Ok(value), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/i32_from_value.rs b/01.workspace/heave/src/imp/i32_from_value.rs deleted file mode 100644 index 836c1fb..0000000 --- a/01.workspace/heave/src/imp/i32_from_value.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::*; - -impl From for i32 { - fn from(value: Value) -> i32 { - match value { - Value::SignedInt(value) => value - .try_into() - .map_err(|_| "Type mismatch".to_string()) - .unwrap(), - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/i32_try_from_value.rs b/01.workspace/heave/src/imp/i32_try_from_value.rs new file mode 100644 index 0000000..63396a4 --- /dev/null +++ b/01.workspace/heave/src/imp/i32_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for i32 { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::SignedInt(value) => value.try_into().map_err(|_| ()), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/i64_from_value.rs b/01.workspace/heave/src/imp/i64_from_value.rs deleted file mode 100644 index e969377..0000000 --- a/01.workspace/heave/src/imp/i64_from_value.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::*; - -impl From for i64 { - fn from(value: Value) -> i64 { - match value { - Value::SignedInt(value) => value, - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/i64_try_from_value.rs b/01.workspace/heave/src/imp/i64_try_from_value.rs new file mode 100644 index 0000000..94720c6 --- /dev/null +++ b/01.workspace/heave/src/imp/i64_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for i64 { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::SignedInt(value) => Ok(value), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/mod.rs b/01.workspace/heave/src/imp/mod.rs index 9882c41..a15767e 100644 --- a/01.workspace/heave/src/imp/mod.rs +++ b/01.workspace/heave/src/imp/mod.rs @@ -1,10 +1,10 @@ -pub mod bool_from_value; -pub mod f64_from_value; -pub mod i32_from_value; -pub mod i64_from_value; -pub mod string_from_value; -pub mod u32_from_value; -pub mod u64_from_value; +pub mod bool_try_from_value; +pub mod f64_try_from_value; +pub mod i32_try_from_value; +pub mod i64_try_from_value; +pub mod string_try_from_value; +pub mod u32_try_from_value; +pub mod u64_try_from_value; pub mod value_from_bool; pub mod value_from_f64; pub mod value_from_i32; diff --git a/01.workspace/heave/src/imp/string_from_value.rs b/01.workspace/heave/src/imp/string_from_value.rs deleted file mode 100644 index 006d3f9..0000000 --- a/01.workspace/heave/src/imp/string_from_value.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::*; - -impl From for String { - fn from(value: Value) -> String { - match value { - Value::Text(value) => value, - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/string_try_from_value.rs b/01.workspace/heave/src/imp/string_try_from_value.rs new file mode 100644 index 0000000..7980840 --- /dev/null +++ b/01.workspace/heave/src/imp/string_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for String { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::Text(value) => Ok(value), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/u32_from_value.rs b/01.workspace/heave/src/imp/u32_from_value.rs deleted file mode 100644 index 6cb44df..0000000 --- a/01.workspace/heave/src/imp/u32_from_value.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::*; - -impl From for u32 { - fn from(value: Value) -> u32 { - match value { - Value::UnsignedInt(value) => value - .try_into() - .map_err(|_| "Type mismatch".to_string()) - .unwrap(), - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/u32_try_from_value.rs b/01.workspace/heave/src/imp/u32_try_from_value.rs new file mode 100644 index 0000000..b92695d --- /dev/null +++ b/01.workspace/heave/src/imp/u32_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for u32 { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::UnsignedInt(value) => value.try_into().map_err(|_| ()), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/imp/u64_from_value.rs b/01.workspace/heave/src/imp/u64_from_value.rs deleted file mode 100644 index b9ed9b6..0000000 --- a/01.workspace/heave/src/imp/u64_from_value.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::*; - -impl From for u64 { - fn from(value: Value) -> u64 { - match value { - Value::UnsignedInt(value) => value, - _ => panic!("Type mismatch"), - } - } -} diff --git a/01.workspace/heave/src/imp/u64_try_from_value.rs b/01.workspace/heave/src/imp/u64_try_from_value.rs new file mode 100644 index 0000000..7b43964 --- /dev/null +++ b/01.workspace/heave/src/imp/u64_try_from_value.rs @@ -0,0 +1,11 @@ +use crate::*; + +impl TryFrom for u64 { + type Error = (); + fn try_from(value: Value) -> Result { + match value { + Value::UnsignedInt(value) => Ok(value), + _ => Err(()), + } + } +} diff --git a/01.workspace/heave/src/str/catalog.rs b/01.workspace/heave/src/str/catalog.rs index f0f98f9..cc1079a 100644 --- a/01.workspace/heave/src/str/catalog.rs +++ b/01.workspace/heave/src/str/catalog.rs @@ -224,9 +224,11 @@ mod tests { fn from(entity: Entity) -> Self { Self { id: entity.id.clone(), - name: entity.unwrap("name"), - price: entity.unwrap("price"), - in_stock: entity.unwrap("in_stock"), + name: entity.unwrap("name").expect("name is always present"), + price: entity.unwrap("price").expect("price is always present"), + in_stock: entity + .unwrap("in_stock") + .expect("in_stock is always present"), } } } diff --git a/01.workspace/heave/src/str/entity.rs b/01.workspace/heave/src/str/entity.rs index 07577a9..a816ce7 100644 --- a/01.workspace/heave/src/str/entity.rs +++ b/01.workspace/heave/src/str/entity.rs @@ -101,9 +101,7 @@ impl Entity { /// Unwraps an attribute's value into a specified type `T`. /// - /// # Panics - /// - /// Panics if the attribute does not exist. + /// This function requires `T` to implement `TryFrom`. /// /// # Arguments /// @@ -111,48 +109,59 @@ impl Entity { /// /// # Returns /// - /// The value of the attribute converted to type `T`. - pub fn unwrap(&self, id: &str) -> T + /// A `Result` which is `Ok(T)` if the conversion is successful, + /// or `Err(FailedTo::ConvertValue)` if it fails. + pub fn unwrap(&self, id: &str) -> Result where - T: From, + T: TryFrom, { self.value_of(id) - .map(|value| T::from(value.clone())) + .map(|value| T::try_from(value.clone()).map_err(|_| FailedTo::ConvertValue)) .unwrap() } /// Unwraps an attribute's value into an `Option`. /// + /// This function requires `T` to implement `TryFrom`. + /// /// # Arguments /// /// * `id` - The ID of the attribute to unwrap. /// /// # Returns /// - /// An `Option` containing the converted value if the attribute exists, otherwise `None`. - pub fn unwrap_opt(&self, id: &str) -> Option + /// A `Result, FailedTo>`. + /// - `Ok(Some(T))` if the attribute exists and the conversion is successful. + /// - `Ok(None)` if the attribute does not exist. + /// - `Err(FailedTo::ConvertValue)` if the attribute exists but the conversion fails. + pub fn unwrap_opt(&self, id: &str) -> Result, FailedTo> where - T: From, - { - self.value_of(id).map(|value| T::from(value.clone())) - } - - /// Unwraps an attribute's value, returning a default if it doesn't exist. - /// - /// # Arguments - /// - /// * `id` - The ID of the attribute to unwrap. - /// * `default` - The default value to return if the attribute is not found. - /// - /// # Returns - /// - /// The converted value of the attribute or the default value. - pub fn unwrap_or(&self, id: &str, default: T) -> T - where - T: From, + T: TryFrom, { self.value_of(id) - .map(|value| T::from(value.clone())) - .unwrap_or(default) + .map(|value| T::try_from(value.clone()).map_err(|_| FailedTo::ConvertValue)) + .transpose() + } + + /// Unwraps an attribute's value, returning a default value if it doesn't exist or fails to convert. + /// + /// This function requires `T` to implement `TryFrom`. + /// + /// # Arguments + /// + /// * `id` - The ID of the attribute to unwrap. + /// * `default` - The default value to return if the attribute is not found or conversion fails. + /// + /// # Returns + /// + /// The converted value of the attribute, or the default value. + pub fn unwrap_or(&self, id: &str, default: T) -> Result + where + T: TryFrom, + { + self.value_of(id) + .map(|value| T::try_from(value.clone()).map_err(|_| FailedTo::ConvertValue)) + .transpose() + .map(|value| value.unwrap_or(default)) } } diff --git a/01.workspace/heave/src/str/failed_to.rs b/01.workspace/heave/src/str/failed_to.rs index 4493b36..2cce39b 100644 --- a/01.workspace/heave/src/str/failed_to.rs +++ b/01.workspace/heave/src/str/failed_to.rs @@ -3,6 +3,8 @@ use crate::*; /// Represents the possible failures that can occur in the library. #[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)] pub enum FailedTo { + /// Failed to convert from Value to type. + ConvertValue, /// Failed to initialize the database. InitDatabase, /// Failed to load data from the database.