Skip to content

Commit 8981b45

Browse files
authored
feat: use TryFrom instead of custom trait for StructValue conversion (#43)
Signed-off-by: YUE Daian <sheepduke@gmail.com>
1 parent a0f9f80 commit 8981b45

File tree

3 files changed

+18
-20
lines changed

3 files changed

+18
-20
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ async fn extended_example() {
160160

161161
#### Getting a Struct from a Provider
162162

163-
It is possible to extract a struct from the provider. Internally, this SDK defines a type `StructValue` to store any structure value. The `client.get_struct_value()` functions takes a type parameter `T`. It will try to parse `StructValue` resolved by the provider to `T`, as long as `T` implements trait `FromStructValue`.
163+
It is possible to extract a struct from the provider. Internally, this SDK defines a type `StructValue` to store any structure value. The `client.get_struct_value()` functions takes a type parameter `T`. It will try to parse `StructValue` resolved by the provider to `T`, as long as `T` implements trait `TryFrom<StructValue>`.
164164

165165
You can pass in a type that satisfies this trait bound. When the conversion fails, it returns an `Err` with `EvaluationReason::TypeMismatch`.
166166

src/api/client.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ pub struct Client {
2525
global_evaluation_context: GlobalEvaluationContext,
2626
}
2727

28-
/// The trait that converts a [`StructValue`] to a custom type.
29-
/// It is used to return a custom type from `get_struct_value` and `get_string_details`.
30-
pub trait FromStructValue<Out = Self> {
31-
/// Construct type with given `value`.
32-
fn from_struct_value(value: &StructValue) -> anyhow::Result<Out>;
33-
}
34-
3528
impl Client {
3629
/// Create a new [`Client`] instance.
3730
pub fn new(
@@ -140,7 +133,7 @@ impl Client {
140133
/// If the resolution fails, the `default_value` is returned.
141134
/// The required type should implement [`From<StructValue>`] trait.
142135
#[allow(unused_variables)]
143-
pub async fn get_struct_value<T: FromStructValue>(
136+
pub async fn get_struct_value<T: TryFrom<StructValue>>(
144137
&self,
145138
flag_key: &str,
146139
evaluation_context: Option<&EvaluationContext>,
@@ -154,7 +147,7 @@ impl Client {
154147
.resolve_struct_value(flag_key, &context)
155148
.await?;
156149

157-
match T::from_struct_value(&result.value) {
150+
match T::try_from(result.value) {
158151
Ok(t) => Ok(t),
159152
Err(error) => Err(EvaluationError {
160153
code: EvaluationErrorCode::TypeMismatch,
@@ -242,7 +235,7 @@ impl Client {
242235
/// Return the [`EvaluationDetails`] with given `flag_key`, `evaluation_context` and
243236
/// `evaluation_options`.
244237
#[allow(unused_variables)]
245-
pub async fn get_struct_details<T: FromStructValue>(
238+
pub async fn get_struct_details<T: TryFrom<StructValue>>(
246239
&self,
247240
flag_key: &str,
248241
evaluation_context: Option<&EvaluationContext>,
@@ -256,7 +249,7 @@ impl Client {
256249
.resolve_struct_value(flag_key, &context)
257250
.await?;
258251

259-
match T::from_struct_value(&result.value) {
252+
match T::try_from(result.value) {
260253
Ok(value) => Ok(EvaluationDetails {
261254
flag_key: flag_key.to_string(),
262255
value,
@@ -322,8 +315,6 @@ mod tests {
322315
Client, EvaluationReason, FlagMetadata, StructValue,
323316
};
324317

325-
use super::FromStructValue;
326-
327318
#[spec(
328319
number = "1.2.2",
329320
text = "The client interface MUST define a metadata member or accessor, containing an immutable name field or accessor of type string, which corresponds to the name value supplied during client creation."
@@ -339,16 +330,23 @@ mod tests {
339330
name: String,
340331
}
341332

342-
impl FromStructValue for Student {
343-
fn from_struct_value(value: &StructValue) -> anyhow::Result<Self> {
333+
impl TryFrom<StructValue> for Student {
334+
type Error = String;
335+
336+
fn try_from(value: StructValue) -> Result<Self, Self::Error> {
344337
Ok(Student {
345-
id: value.fields.get("id").unwrap().as_i64().unwrap(),
338+
id: value
339+
.fields
340+
.get("id")
341+
.ok_or("id not provided")?
342+
.as_i64()
343+
.ok_or("id is not a valid number")?,
346344
name: value
347345
.fields
348346
.get("name")
349-
.unwrap()
347+
.ok_or("name not provided")?
350348
.as_str()
351-
.unwrap()
349+
.ok_or("name is not a valid string")?
352350
.to_string(),
353351
})
354352
}

src/api/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod api;
22
pub use api::OpenFeature;
33

44
mod client;
5-
pub use client::{Client, ClientMetadata, FromStructValue};
5+
pub use client::{Client, ClientMetadata};
66

77
mod provider_registry;
88

0 commit comments

Comments
 (0)