Skip to content

Commit dc575c3

Browse files
committed
functora-tagger refactoring
1 parent d181c0b commit dc575c3

File tree

6 files changed

+296
-287
lines changed

6 files changed

+296
-287
lines changed

rust/functora-tagged/src/infallible.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::convert::Infallible;
1+
pub use std::convert::Infallible;
22

33
pub trait InfallibleInto<T> {
44
fn infallible(self) -> T;

rust/functora-tagged/src/lib.rs

Lines changed: 6 additions & 281 deletions
Original file line numberDiff line numberDiff line change
@@ -1,286 +1,11 @@
11
#![doc = include_str!("../README.md")]
2-
use derive_more::Display;
3-
use std::error::Error;
4-
use std::fmt::{Debug, Display};
5-
use std::hash::{Hash, Hasher};
6-
use std::marker::PhantomData;
7-
use std::ops::Deref;
8-
use std::str::FromStr;
92
pub mod infallible;
103
pub use infallible::*;
114
pub mod via_string;
125
pub use via_string::*;
13-
14-
#[derive(Debug)]
15-
pub struct Tagged<Rep, Tag>(Rep, PhantomData<Tag>);
16-
17-
pub trait Refine<Rep>: Sized {
18-
type RefineError;
19-
20-
fn refine(rep: Rep) -> Result<Rep, Self::RefineError> {
21-
Ok(rep)
22-
}
23-
}
24-
25-
impl<Rep, Tag> Tagged<Rep, Tag> {
26-
pub fn new(rep: Rep) -> Result<Self, Tag::RefineError>
27-
where
28-
Tag: Refine<Rep>,
29-
{
30-
Tag::refine(rep).map(|rep| Tagged(rep, PhantomData))
31-
}
32-
pub fn rep(&self) -> &Rep {
33-
&self.0
34-
}
35-
}
36-
37-
impl<Rep: Eq, Tag> Eq for Tagged<Rep, Tag> {}
38-
39-
impl<Rep: PartialEq, Tag> PartialEq for Tagged<Rep, Tag> {
40-
fn eq(&self, other: &Self) -> bool {
41-
self.rep() == other.rep()
42-
}
43-
}
44-
45-
impl<Rep: Ord, Tag> Ord for Tagged<Rep, Tag> {
46-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
47-
self.rep().cmp(other.rep())
48-
}
49-
}
50-
51-
impl<Rep: PartialOrd, Tag> PartialOrd for Tagged<Rep, Tag> {
52-
fn partial_cmp(
53-
&self,
54-
other: &Self,
55-
) -> Option<std::cmp::Ordering> {
56-
self.rep().partial_cmp(other.rep())
57-
}
58-
}
59-
60-
impl<Rep: Clone, Tag> Clone for Tagged<Rep, Tag> {
61-
fn clone(&self) -> Self {
62-
Tagged(self.rep().clone(), PhantomData)
63-
}
64-
}
65-
66-
impl<Rep: Display, Tag> Display for Tagged<Rep, Tag> {
67-
fn fmt(
68-
&self,
69-
f: &mut std::fmt::Formatter<'_>,
70-
) -> std::fmt::Result {
71-
self.rep().fmt(f)
72-
}
73-
}
74-
75-
impl<Rep: Hash, Tag> Hash for Tagged<Rep, Tag> {
76-
fn hash<H: Hasher>(&self, state: &mut H) {
77-
self.rep().hash(state);
78-
}
79-
}
80-
81-
impl<Rep, Tag> Deref for Tagged<Rep, Tag> {
82-
type Target = Rep;
83-
84-
fn deref(&self) -> &Self::Target {
85-
self.rep()
86-
}
87-
}
88-
89-
#[derive(Debug, Display)]
90-
pub enum ParseError<Rep, Tag>
91-
where
92-
Rep: FromStr,
93-
Tag: Refine<Rep>,
94-
{
95-
Decode(Rep::Err),
96-
Refine(Tag::RefineError),
97-
}
98-
99-
impl<Rep, Tag> Error for ParseError<Rep, Tag>
100-
where
101-
Rep: Debug + FromStr,
102-
Tag: Debug + Refine<Rep>,
103-
Rep::Err: Debug + Display,
104-
Tag::RefineError: Debug + Display,
105-
{
106-
}
107-
108-
impl<Rep, Tag> Eq for ParseError<Rep, Tag>
109-
where
110-
Rep: FromStr,
111-
Tag: Refine<Rep>,
112-
Rep::Err: Eq,
113-
Tag::RefineError: Eq,
114-
{
115-
}
116-
117-
impl<Rep, Tag> PartialEq for ParseError<Rep, Tag>
118-
where
119-
Rep: FromStr,
120-
Tag: Refine<Rep>,
121-
Rep::Err: PartialEq,
122-
Tag::RefineError: PartialEq,
123-
{
124-
fn eq(&self, other: &Self) -> bool {
125-
match (self, other) {
126-
(
127-
ParseError::Decode(a),
128-
ParseError::Decode(b),
129-
) => a == b,
130-
(
131-
ParseError::Refine(a),
132-
ParseError::Refine(b),
133-
) => a == b,
134-
_ => false,
135-
}
136-
}
137-
}
138-
139-
impl<Rep, Tag> Clone for ParseError<Rep, Tag>
140-
where
141-
Rep: FromStr,
142-
Tag: Refine<Rep>,
143-
Rep::Err: Clone,
144-
Tag::RefineError: Clone,
145-
{
146-
fn clone(&self) -> Self {
147-
match self {
148-
ParseError::Decode(err) => {
149-
ParseError::Decode(err.clone())
150-
}
151-
ParseError::Refine(err) => {
152-
ParseError::Refine(err.clone())
153-
}
154-
}
155-
}
156-
}
157-
158-
impl<Rep, Tag> FromStr for Tagged<Rep, Tag>
159-
where
160-
Rep: FromStr,
161-
Tag: Refine<Rep>,
162-
{
163-
type Err = ParseError<Rep, Tag>;
164-
fn from_str(s: &str) -> Result<Self, Self::Err> {
165-
Tagged::new(
166-
Rep::from_str(s).map_err(ParseError::Decode)?,
167-
)
168-
.map_err(ParseError::Refine)
169-
}
170-
}
171-
172-
#[cfg(feature = "serde")]
173-
use serde::{Deserialize, Serialize};
174-
175-
#[cfg(feature = "serde")]
176-
impl<Rep: Serialize, Tag> Serialize for Tagged<Rep, Tag> {
177-
fn serialize<S>(
178-
&self,
179-
serializer: S,
180-
) -> Result<S::Ok, S::Error>
181-
where
182-
S: serde::Serializer,
183-
{
184-
self.rep().serialize(serializer)
185-
}
186-
}
187-
188-
#[cfg(feature = "serde")]
189-
impl<'de, Rep, Tag> Deserialize<'de> for Tagged<Rep, Tag>
190-
where
191-
Rep: Deserialize<'de>,
192-
Tag: Refine<Rep>,
193-
Tag::RefineError: Display,
194-
{
195-
fn deserialize<D>(
196-
deserializer: D,
197-
) -> Result<Self, D::Error>
198-
where
199-
D: serde::Deserializer<'de>,
200-
{
201-
Rep::deserialize(deserializer).and_then(|rep| {
202-
Tagged::new(rep)
203-
.map_err(serde::de::Error::custom)
204-
})
205-
}
206-
}
207-
208-
#[cfg(feature = "diesel")]
209-
mod diesel_impl {
210-
use crate::*;
211-
use diesel::Queryable;
212-
use diesel::backend::Backend;
213-
use diesel::deserialize::FromSql;
214-
use diesel::expression::AsExpression;
215-
use diesel::serialize::{Output, ToSql};
216-
use diesel::sql_types::SingleValue;
217-
use std::error::Error;
218-
219-
impl<Rep, Tag, ST> AsExpression<ST> for Tagged<Rep, Tag>
220-
where
221-
Rep: Clone + AsExpression<ST>,
222-
ST: SingleValue,
223-
{
224-
type Expression = Rep::Expression;
225-
fn as_expression(self) -> Self::Expression {
226-
self.rep().clone().as_expression()
227-
}
228-
}
229-
230-
impl<Rep, Tag, ST> AsExpression<ST> for &Tagged<Rep, Tag>
231-
where
232-
Rep: Clone + AsExpression<ST>,
233-
ST: SingleValue,
234-
{
235-
type Expression = Rep::Expression;
236-
fn as_expression(self) -> Self::Expression {
237-
self.rep().clone().as_expression()
238-
}
239-
}
240-
241-
impl<DB, Rep, Tag, ST> ToSql<ST, DB> for Tagged<Rep, Tag>
242-
where
243-
Rep: ToSql<ST, DB>,
244-
DB: Backend,
245-
Tag: Debug,
246-
{
247-
fn to_sql<'a>(
248-
&'a self,
249-
out: &mut Output<'a, '_, DB>,
250-
) -> diesel::serialize::Result {
251-
self.rep().to_sql(out)
252-
}
253-
}
254-
255-
impl<DB, Rep, Tag, ST> FromSql<ST, DB> for Tagged<Rep, Tag>
256-
where
257-
Rep: FromSql<ST, DB>,
258-
Tag: Refine<Rep>,
259-
Tag::RefineError: 'static + Error + Send + Sync,
260-
DB: Backend,
261-
{
262-
fn from_sql(
263-
bytes: DB::RawValue<'_>,
264-
) -> diesel::deserialize::Result<Self> {
265-
let rep = Rep::from_sql(bytes)?;
266-
Ok(Tagged::new(rep).map_err(Box::new)?)
267-
}
268-
}
269-
270-
impl<Rep, Tag, ST, DB> Queryable<ST, DB>
271-
for Tagged<Rep, Tag>
272-
where
273-
Rep: Queryable<ST, DB>,
274-
Tag: Refine<Rep>,
275-
Tag::RefineError: 'static + Error + Send + Sync,
276-
DB: Backend,
277-
{
278-
type Row = Rep::Row;
279-
fn build(
280-
row: Self::Row,
281-
) -> diesel::deserialize::Result<Self> {
282-
let rep = Queryable::build(row)?;
283-
Ok(Tagged::new(rep).map_err(Box::new)?)
284-
}
285-
}
286-
}
6+
pub mod parse_error;
7+
pub use parse_error::*;
8+
pub mod refine;
9+
pub use refine::*;
10+
pub mod tagged;
11+
pub use tagged::*;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use crate::*;
2+
pub use derive_more::Display;
3+
pub use std::error::Error;
4+
pub use std::fmt::{Debug, Display};
5+
pub use std::str::FromStr;
6+
7+
#[derive(Debug, Display)]
8+
pub enum ParseError<Rep, Tag>
9+
where
10+
Rep: FromStr,
11+
Tag: Refine<Rep>,
12+
{
13+
Decode(Rep::Err),
14+
Refine(Tag::RefineError),
15+
}
16+
17+
impl<Rep, Tag> Error for ParseError<Rep, Tag>
18+
where
19+
Rep: Debug + FromStr,
20+
Tag: Debug + Refine<Rep>,
21+
Rep::Err: Debug + Display,
22+
Tag::RefineError: Debug + Display,
23+
{
24+
}
25+
26+
impl<Rep, Tag> Eq for ParseError<Rep, Tag>
27+
where
28+
Rep: FromStr,
29+
Tag: Refine<Rep>,
30+
Rep::Err: Eq,
31+
Tag::RefineError: Eq,
32+
{
33+
}
34+
35+
impl<Rep, Tag> PartialEq for ParseError<Rep, Tag>
36+
where
37+
Rep: FromStr,
38+
Tag: Refine<Rep>,
39+
Rep::Err: PartialEq,
40+
Tag::RefineError: PartialEq,
41+
{
42+
fn eq(&self, other: &Self) -> bool {
43+
match (self, other) {
44+
(
45+
ParseError::Decode(a),
46+
ParseError::Decode(b),
47+
) => a == b,
48+
(
49+
ParseError::Refine(a),
50+
ParseError::Refine(b),
51+
) => a == b,
52+
_ => false,
53+
}
54+
}
55+
}
56+
57+
impl<Rep, Tag> Clone for ParseError<Rep, Tag>
58+
where
59+
Rep: FromStr,
60+
Tag: Refine<Rep>,
61+
Rep::Err: Clone,
62+
Tag::RefineError: Clone,
63+
{
64+
fn clone(&self) -> Self {
65+
match self {
66+
ParseError::Decode(err) => {
67+
ParseError::Decode(err.clone())
68+
}
69+
ParseError::Refine(err) => {
70+
ParseError::Refine(err.clone())
71+
}
72+
}
73+
}
74+
}

rust/functora-tagged/src/refine.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub trait Refine<Rep>: Sized {
2+
type RefineError;
3+
4+
fn refine(rep: Rep) -> Result<Rep, Self::RefineError> {
5+
Ok(rep)
6+
}
7+
}

0 commit comments

Comments
 (0)