Skip to content

Commit 3cd632a

Browse files
authored
Merge pull request #25 from tomoikey/feat/try_from
implement try_from
2 parents 49b926e + 693db25 commit 3cd632a

File tree

3 files changed

+155
-3
lines changed

3 files changed

+155
-3
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ repository = "https://github.com/tomoikey/refined_type"
66
readme = "README.md"
77
categories = ["accessibility", "development-tools", "rust-patterns"]
88
license = "MIT"
9-
version = "0.5.14"
9+
version = "0.5.15"
1010
edition = "2021"
1111

1212
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -17,5 +17,5 @@ regex = "1.11.1"
1717
serde = { version = "1.0.214", features = ["derive"] }
1818

1919
[dev-dependencies]
20-
anyhow = "1.0.89"
20+
anyhow = "1.0.92"
2121
serde_json = "1.0.128"

src/refined.rs

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::result::Error;
22
use crate::rule::Rule;
33
use serde::{Deserialize, Deserializer, Serialize, Serializer};
4+
use std::collections::{HashMap, HashSet, VecDeque};
45
use std::fmt::{Debug, Display, Formatter};
56

67
/// Refined is a versatile type in ensuring that `T` satisfies the conditions of `RULE` (predicate type)
@@ -85,6 +86,64 @@ where
8586
}
8687
}
8788

89+
macro_rules! impl_try_from {
90+
($t: ty) => {
91+
impl<RULE: Rule<Item = $t>> TryFrom<$t> for Refined<RULE> {
92+
type Error = Error<$t>;
93+
94+
fn try_from(value: $t) -> Result<Self, Self::Error> {
95+
Refined::new(value)
96+
}
97+
}
98+
};
99+
($($ts: ty), +) => {
100+
$(impl_try_from!($ts);)+
101+
};
102+
}
103+
104+
impl_try_from![u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64];
105+
impl_try_from![String, char];
106+
107+
impl<'a, RULE: Rule<Item = String>> TryFrom<&'a str> for Refined<RULE> {
108+
type Error = Error<String>;
109+
110+
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
111+
Refined::new(value.into())
112+
}
113+
}
114+
115+
impl<T, RULE: Rule<Item = Vec<T>>> TryFrom<Vec<T>> for Refined<RULE> {
116+
type Error = Error<Vec<T>>;
117+
118+
fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
119+
Refined::new(value)
120+
}
121+
}
122+
123+
impl<T, RULE: Rule<Item = VecDeque<T>>> TryFrom<VecDeque<T>> for Refined<RULE> {
124+
type Error = Error<VecDeque<T>>;
125+
126+
fn try_from(value: VecDeque<T>) -> Result<Self, Self::Error> {
127+
Refined::new(value)
128+
}
129+
}
130+
131+
impl<T, RULE: Rule<Item = HashSet<T>>> TryFrom<HashSet<T>> for Refined<RULE> {
132+
type Error = Error<HashSet<T>>;
133+
134+
fn try_from(value: HashSet<T>) -> Result<Self, Self::Error> {
135+
Refined::new(value)
136+
}
137+
}
138+
139+
impl<K, V, RULE: Rule<Item = HashMap<K, V>>> TryFrom<HashMap<K, V>> for Refined<RULE> {
140+
type Error = Error<HashMap<K, V>>;
141+
142+
fn try_from(value: HashMap<K, V>) -> Result<Self, Self::Error> {
143+
Refined::new(value)
144+
}
145+
}
146+
88147
impl<RULE, T> Display for Refined<RULE>
89148
where
90149
RULE: Rule<Item = T>,
@@ -99,10 +158,15 @@ where
99158
mod test {
100159
use serde::{Deserialize, Serialize};
101160
use serde_json::json;
161+
use std::collections::{HashMap, HashSet, VecDeque};
102162

103163
use crate::refined::Refined;
104164
use crate::result::Error;
105-
use crate::rule::{NonEmptyString, NonEmptyStringRule, NonEmptyVec};
165+
use crate::rule::{
166+
EqualI128, EqualI16, EqualI32, EqualI64, EqualI8, EqualIsize, EqualU128, EqualU16,
167+
EqualU32, EqualU64, EqualU8, EqualUsize, NonEmptyHashMap, NonEmptyHashSet, NonEmptyString,
168+
NonEmptyStringRule, NonEmptyVec, NonEmptyVecDeque,
169+
};
106170

107171
#[test]
108172
fn test_unsafe_new_success() {
@@ -255,4 +319,86 @@ mod test {
255319
assert!(result.is_err());
256320
Ok(())
257321
}
322+
323+
#[test]
324+
fn test_try_from() -> anyhow::Result<()> {
325+
let value = NonEmptyString::try_from("hello")?;
326+
assert_eq!(value.into_value(), "hello");
327+
328+
let value = NonEmptyString::try_from("hello".to_string())?;
329+
assert_eq!(value.into_value(), "hello");
330+
331+
let value = EqualU8::<8>::try_from(8)?;
332+
assert_eq!(value.into_value(), 8);
333+
334+
let value = EqualU16::<16>::try_from(16)?;
335+
assert_eq!(value.into_value(), 16);
336+
337+
let value = EqualU32::<32>::try_from(32)?;
338+
assert_eq!(value.into_value(), 32);
339+
340+
let value = EqualU64::<64>::try_from(64)?;
341+
assert_eq!(value.into_value(), 64);
342+
343+
let value = EqualU128::<128>::try_from(128)?;
344+
assert_eq!(value.into_value(), 128);
345+
346+
let value = EqualUsize::<1>::try_from(1)?;
347+
assert_eq!(value.into_value(), 1);
348+
349+
let value = EqualI8::<8>::try_from(8)?;
350+
assert_eq!(value.into_value(), 8);
351+
352+
let value = EqualI16::<16>::try_from(16)?;
353+
assert_eq!(value.into_value(), 16);
354+
355+
let value = EqualI32::<32>::try_from(32)?;
356+
assert_eq!(value.into_value(), 32);
357+
358+
let value = EqualI64::<64>::try_from(64)?;
359+
assert_eq!(value.into_value(), 64);
360+
361+
let value = EqualI128::<128>::try_from(128)?;
362+
assert_eq!(value.into_value(), 128);
363+
364+
let value = EqualIsize::<1>::try_from(1)?;
365+
assert_eq!(value.into_value(), 1);
366+
367+
let value = NonEmptyVec::try_from(vec!["hello".to_string()])?;
368+
assert_eq!(value.into_value(), vec!["hello".to_string()]);
369+
370+
let value = NonEmptyVecDeque::try_from(
371+
vec!["hello".to_string()]
372+
.into_iter()
373+
.collect::<VecDeque<_>>(),
374+
)?;
375+
assert_eq!(value.into_value(), vec!["hello".to_string()]);
376+
377+
let value = NonEmptyHashSet::try_from(
378+
vec!["hello".to_string()]
379+
.into_iter()
380+
.collect::<HashSet<_>>(),
381+
)?;
382+
assert_eq!(
383+
value.into_value(),
384+
vec!["hello".to_string()].into_iter().collect()
385+
);
386+
387+
let value = NonEmptyHashMap::try_from(
388+
vec![("hello".to_string(), "world".to_string())]
389+
.into_iter()
390+
.collect::<HashMap<_, _>>(),
391+
)?;
392+
assert_eq!(
393+
value.into_value(),
394+
vec![("hello".to_string(), "world".to_string())]
395+
.into_iter()
396+
.collect()
397+
);
398+
399+
let value: NonEmptyVec<NonEmptyString> =
400+
NonEmptyVec::try_from(vec!["hello".to_string().try_into()?])?;
401+
assert_eq!(value.into_value(), vec!["hello".to_string().try_into()?]);
402+
Ok(())
403+
}
258404
}

src/result.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ impl<T> Error<T> {
2323
}
2424
}
2525

26+
impl<T: Debug> std::error::Error for Error<T> {
27+
fn description(&self) -> &str {
28+
&self.message
29+
}
30+
}
31+
2632
impl<T> Display for Error<T> {
2733
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2834
write!(f, "{}", self.message)

0 commit comments

Comments
 (0)