Skip to content

Commit fd740a0

Browse files
committed
Improve ergonomics, vol.1
1 parent db9a189 commit fd740a0

File tree

10 files changed

+86
-74
lines changed

10 files changed

+86
-74
lines changed

juniper/src/integrations/bigdecimal.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//!
99
//! [`BigDecimal`]: bigdecimal::BigDecimal
1010
11-
use crate::graphql_scalar;
11+
use crate::{ScalarValue, graphql_scalar};
1212

1313
// TODO: Try remove on upgrade of `bigdecimal` crate.
1414
mod for_minimal_versions_check_only {
@@ -30,6 +30,7 @@ mod for_minimal_versions_check_only {
3030
#[graphql_scalar]
3131
#[graphql(
3232
with = bigdecimal_scalar,
33+
to_output_with = ScalarValue::from_displayable,
3334
parse_token(i32, f64, String),
3435
specified_by_url = "https://docs.rs/bigdecimal",
3536
)]
@@ -39,10 +40,6 @@ mod bigdecimal_scalar {
3940
use super::BigDecimal;
4041
use crate::{Scalar, ScalarValue};
4142

42-
pub(super) fn to_output(v: &BigDecimal) -> String {
43-
v.to_string() // TODO: Optimize via `Display`?
44-
}
45-
4643
pub(super) fn from_input(v: &Scalar<impl ScalarValue>) -> Result<BigDecimal, Box<str>> {
4744
if let Some(i) = v.try_to_int() {
4845
Ok(BigDecimal::from(i))

juniper/src/integrations/chrono.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@ use crate::graphql_scalar;
4545
pub type LocalDate = chrono::NaiveDate;
4646

4747
mod local_date {
48+
use std::fmt::Display;
49+
4850
use super::LocalDate;
4951

5052
/// Format of a [`LocalDate` scalar][1].
5153
///
5254
/// [1]: https://graphql-scalars.dev/docs/scalars/local-date
5355
const FORMAT: &str = "%Y-%m-%d";
5456

55-
pub(super) fn to_output(v: &LocalDate) -> String {
56-
v.format(FORMAT).to_string() // TODO: Optimize via `Display`?
57+
pub(super) fn to_output(v: &LocalDate) -> impl Display {
58+
v.format(FORMAT)
5759
}
5860

5961
pub(super) fn from_input(s: &str) -> Result<LocalDate, Box<str>> {
@@ -82,6 +84,8 @@ mod local_date {
8284
pub type LocalTime = chrono::NaiveTime;
8385

8486
mod local_time {
87+
use std::fmt::Display;
88+
8589
use chrono::Timelike as _;
8690

8791
use super::LocalTime;
@@ -101,13 +105,12 @@ mod local_time {
101105
/// [1]: https://graphql-scalars.dev/docs/scalars/local-time
102106
const FORMAT_NO_SECS: &str = "%H:%M";
103107

104-
pub(super) fn to_output(v: &LocalTime) -> String {
108+
pub(super) fn to_output(v: &LocalTime) -> impl Display {
105109
if v.nanosecond() == 0 {
106110
v.format(FORMAT_NO_MILLIS)
107111
} else {
108112
v.format(FORMAT)
109113
}
110-
.to_string() // TODO: Optimize via `Display`?
111114
}
112115

113116
pub(super) fn from_input(s: &str) -> Result<LocalTime, Box<str>> {
@@ -137,15 +140,17 @@ mod local_time {
137140
pub type LocalDateTime = chrono::NaiveDateTime;
138141

139142
mod local_date_time {
143+
use std::fmt::Display;
144+
140145
use super::LocalDateTime;
141146

142147
/// Format of a [`LocalDateTime` scalar][1].
143148
///
144149
/// [1]: https://graphql-scalars.dev/docs/scalars/local-date-time
145150
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
146151

147-
pub(super) fn to_output(v: &LocalDateTime) -> String {
148-
v.format(FORMAT).to_string() // TODO: Optimize via `Display`?
152+
pub(super) fn to_output(v: &LocalDateTime) -> impl Display {
153+
v.format(FORMAT)
149154
}
150155

151156
pub(super) fn from_input(s: &str) -> Result<LocalDateTime, Box<str>> {
@@ -191,7 +196,7 @@ mod date_time {
191196
Tz::Offset: fmt::Display,
192197
{
193198
v.with_timezone(&Utc)
194-
.to_rfc3339_opts(SecondsFormat::AutoSi, true) // TODO: Optimize via `Display`?
199+
.to_rfc3339_opts(SecondsFormat::AutoSi, true)
195200
}
196201

197202
pub(super) fn from_input<Tz>(s: &str) -> Result<DateTime<Tz>, Box<str>>

juniper/src/integrations/jiff.rs

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use std::str;
5454

5555
use derive_more::with_trait::{Debug, Display, Error, Into};
5656

57-
use crate::graphql_scalar;
57+
use crate::{ScalarValue, graphql_scalar};
5858

5959
/// Representation of a civil date in the Gregorian calendar.
6060
///
@@ -84,8 +84,8 @@ mod local_date {
8484
/// [1]: https://graphql-scalars.dev/docs/scalars/local-date
8585
const FORMAT: &str = "%Y-%m-%d";
8686

87-
pub(super) fn to_output(v: &LocalDate) -> String {
88-
v.strftime(FORMAT).to_string() // TODO: Optimize via `Display`?
87+
pub(super) fn to_output(v: &LocalDate) -> impl Display {
88+
v.strftime(FORMAT)
8989
}
9090

9191
pub(super) fn from_input(s: &str) -> Result<LocalDate, Box<str>> {
@@ -131,13 +131,12 @@ mod local_time {
131131
/// [1]: https://graphql-scalars.dev/docs/scalars/local-time
132132
const FORMAT_NO_SECS: &str = "%H:%M";
133133

134-
pub(super) fn to_output(v: &LocalTime) -> String {
134+
pub(super) fn to_output(v: &LocalTime) -> impl Display {
135135
if v.subsec_nanosecond() == 0 {
136136
v.strftime(FORMAT_NO_MILLIS)
137137
} else {
138138
v.strftime(FORMAT)
139139
}
140-
.to_string() // TODO: Optimize via `Display`?
141140
}
142141

143142
pub(super) fn from_input(s: &str) -> Result<LocalTime, Box<str>> {
@@ -180,8 +179,8 @@ mod local_date_time {
180179
/// [1]: https://graphql-scalars.dev/docs/scalars/local-date-time
181180
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
182181

183-
pub(super) fn to_output(v: &LocalDateTime) -> String {
184-
v.strftime(FORMAT).to_string() // TODO: Optimize via `Display`?
182+
pub(super) fn to_output(v: &LocalDateTime) -> impl Display {
183+
v.strftime(FORMAT)
185184
}
186185

187186
pub(super) fn from_input(s: &str) -> Result<LocalDateTime, Box<str>> {
@@ -209,21 +208,20 @@ mod local_date_time {
209208
pub type DateTime = jiff::Timestamp;
210209

211210
mod date_time {
212-
use std::str::FromStr as _;
213-
214211
use super::*;
215212

216213
/// Format of a [`DateTime` scalar][1].
217214
///
218215
/// [1]: https://graphql-scalars.dev/docs/scalars/date-time
219216
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.fZ";
220217

221-
pub(super) fn to_output(v: &DateTime) -> String {
222-
v.strftime(FORMAT).to_string() // TODO: Optimize via `Display`?
218+
pub(super) fn to_output(v: &DateTime) -> impl Display {
219+
v.strftime(FORMAT)
223220
}
224221

225222
pub(super) fn from_input(s: &str) -> Result<DateTime, Box<str>> {
226-
DateTime::from_str(s).map_err(|e| format!("Invalid `DateTime`: {e}").into())
223+
s.parse()
224+
.map_err(|e| format!("Invalid `DateTime`: {e}").into())
227225
}
228226
}
229227

@@ -246,22 +244,18 @@ mod date_time {
246244
#[graphql_scalar]
247245
#[graphql(
248246
with = zoned_date_time,
247+
to_output_with = ScalarValue::from_displayable,
249248
parse_token(String),
250249
specified_by_url = "https://datatracker.ietf.org/doc/html/rfc9557#section-4.1",
251250
)]
252251
pub type ZonedDateTime = jiff::Zoned;
253252

254253
mod zoned_date_time {
255-
use std::str::FromStr as _;
256-
257-
use super::*;
258-
259-
pub(super) fn to_output(v: &ZonedDateTime) -> String {
260-
v.to_string() // TODO: Optimize via `Display`?
261-
}
254+
use super::ZonedDateTime;
262255

263256
pub(super) fn from_input(s: &str) -> Result<ZonedDateTime, Box<str>> {
264-
ZonedDateTime::from_str(s).map_err(|e| format!("Invalid `ZonedDateTime`: {e}").into())
257+
s.parse()
258+
.map_err(|e| format!("Invalid `ZonedDateTime`: {e}").into())
265259
}
266260
}
267261

@@ -279,22 +273,18 @@ mod zoned_date_time {
279273
#[graphql_scalar]
280274
#[graphql(
281275
with = duration,
276+
to_output_with = ScalarValue::from_displayable,
282277
parse_token(String),
283278
specified_by_url = "https://graphql-scalars.dev/docs/scalars/duration",
284279
)]
285280
pub type Duration = jiff::Span;
286281

287282
mod duration {
288-
use std::str::FromStr as _;
289-
290-
use super::*;
291-
292-
pub(super) fn to_output(v: &Duration) -> String {
293-
v.to_string() // TODO: Optimize via `Display`?
294-
}
283+
use super::Duration;
295284

296285
pub(super) fn from_input(s: &str) -> Result<Duration, Box<str>> {
297-
Duration::from_str(s).map_err(|e| format!("Invalid `Duration`: {e}").into())
286+
s.parse()
287+
.map_err(|e| format!("Invalid `Duration`: {e}").into())
298288
}
299289
}
300290

@@ -379,6 +369,7 @@ pub enum TimeZoneParsingError {
379369
#[graphql_scalar]
380370
#[graphql(
381371
with = time_zone,
372+
to_output_with = ScalarValue::from_displayable,
382373
parse_token(String),
383374
specified_by_url = "https://graphql-scalars.dev/docs/scalars/time-zone",
384375
)]
@@ -408,11 +399,7 @@ impl str::FromStr for TimeZone {
408399
}
409400

410401
mod time_zone {
411-
use super::*;
412-
413-
pub(super) fn to_output(v: &TimeZone) -> String {
414-
v.to_string() // TODO: Optimize via `Display`?
415-
}
402+
use super::TimeZone;
416403

417404
pub(super) fn from_input(s: &str) -> Result<TimeZone, Box<str>> {
418405
s.parse()

juniper/src/integrations/rust_decimal.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//!
99
//! [`Decimal`]: rust_decimal::Decimal
1010
11-
use crate::graphql_scalar;
11+
use crate::{ScalarValue, graphql_scalar};
1212

1313
/// 128 bit representation of a fixed-precision decimal number.
1414
///
@@ -27,6 +27,7 @@ use crate::graphql_scalar;
2727
#[graphql_scalar]
2828
#[graphql(
2929
with = rust_decimal_scalar,
30+
to_output_with = ScalarValue::from_displayable,
3031
parse_token(i32, f64, String),
3132
specified_by_url = "https://docs.rs/rust_decimal",
3233
)]
@@ -36,10 +37,6 @@ mod rust_decimal_scalar {
3637
use super::Decimal;
3738
use crate::{Scalar, ScalarValue};
3839

39-
pub(super) fn to_output(v: &Decimal) -> String {
40-
v.to_string() // TODO: Optimize via `Display`?
41-
}
42-
4340
pub(super) fn from_input(v: &Scalar<impl ScalarValue>) -> Result<Decimal, Box<str>> {
4441
if let Some(i) = v.try_to_int() {
4542
Ok(Decimal::from(i))

juniper/src/integrations/time.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ mod local_date {
5757
const FORMAT: &[BorrowedFormatItem<'_>] = format_description!("[year]-[month]-[day]");
5858

5959
pub(super) fn to_output(v: &LocalDate) -> String {
60-
// TODO: Optimize via `Display`?
6160
v.format(FORMAT)
6261
.unwrap_or_else(|e| panic!("failed to format `LocalDate`: {e}"))
6362
}
@@ -108,7 +107,6 @@ mod local_time {
108107
const FORMAT_NO_SECS: &[BorrowedFormatItem<'_>] = format_description!("[hour]:[minute]");
109108

110109
pub(super) fn to_output(v: &LocalTime) -> String {
111-
// TODO: Optimize via `Display`?
112110
if v.millisecond() == 0 {
113111
v.format(FORMAT_NO_MILLIS)
114112
} else {
@@ -153,7 +151,6 @@ mod local_date_time {
153151
format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
154152

155153
pub(super) fn to_output(v: &LocalDateTime) -> String {
156-
// TODO: Optimize via `Display`?
157154
v.format(FORMAT)
158155
.unwrap_or_else(|e| panic!("failed to format `LocalDateTime`: {e}"))
159156
}
@@ -187,7 +184,6 @@ mod date_time {
187184
use super::*;
188185

189186
pub(super) fn to_output(v: &DateTime) -> String {
190-
// TODO: Optimize via `Display`?
191187
v.to_offset(UtcOffset::UTC)
192188
.format(&Rfc3339)
193189
.unwrap_or_else(|e| panic!("failed to format `DateTime`: {e}"))
@@ -227,7 +223,6 @@ mod utc_offset {
227223
use super::*;
228224

229225
pub(super) fn to_output(v: &UtcOffset) -> String {
230-
// TODO: Optimize via `Display`?
231226
v.format(UTC_OFFSET_FORMAT)
232227
.unwrap_or_else(|e| panic!("failed to format `UtcOffset`: {e}"))
233228
}

juniper/src/integrations/uuid.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! [`Uuid`]: uuid::Uuid
1010
//! [s1]: https://graphql-scalars.dev/docs/scalars/uuid
1111
12-
use crate::graphql_scalar;
12+
use crate::{ScalarValue, graphql_scalar};
1313

1414
/// [Universally Unique Identifier][0] (UUID).
1515
///
@@ -24,6 +24,7 @@ use crate::graphql_scalar;
2424
#[graphql(
2525
name = "UUID",
2626
with = uuid_scalar,
27+
to_output_with = ScalarValue::from_displayable,
2728
parse_token(String),
2829
specified_by_url = "https://graphql-scalars.dev/docs/scalars/uuid",
2930
)]
@@ -32,10 +33,6 @@ type Uuid = uuid::Uuid;
3233
mod uuid_scalar {
3334
use super::Uuid;
3435

35-
pub(super) fn to_output(v: &Uuid) -> String {
36-
v.to_string() // TODO: Optimize via `Display`?
37-
}
38-
3936
pub(super) fn from_input(s: &str) -> Result<Uuid, Box<str>> {
4037
Uuid::parse_str(s).map_err(|e| format!("Failed to parse `UUID`: {e}").into())
4138
}

juniper/src/macros/helper/mod.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,31 @@ pub trait ToScalarValueCall<S: ScalarValue> {
107107
fn __to_scalar_value_call(&self, input: Self::Input) -> S;
108108
}
109109

110-
impl<I, S: ScalarValue> ToScalarValueCall<S> for &fn(I) -> S {
110+
impl<I, S> ToScalarValueCall<S> for &&&fn(I) -> S
111+
where
112+
S: ScalarValue,
113+
{
111114
type Input = I;
112115

113116
fn __to_scalar_value_call(&self, input: Self::Input) -> S {
114117
self(input)
115118
}
116119
}
117120

118-
impl<I, O, S: ScalarValue> ToScalarValueCall<S> for fn(I) -> O
121+
impl<I, S> ToScalarValueCall<S> for &&fn(I) -> String
122+
where
123+
S: ScalarValue,
124+
{
125+
type Input = I;
126+
127+
fn __to_scalar_value_call(&self, input: Self::Input) -> S {
128+
self(input).into()
129+
}
130+
}
131+
132+
impl<I, O, S> ToScalarValueCall<S> for &fn(I) -> O
119133
where
134+
S: ScalarValue,
120135
O: ToScalarValue<S>,
121136
{
122137
type Input = I;
@@ -125,3 +140,15 @@ where
125140
self(input).to_scalar_value()
126141
}
127142
}
143+
144+
impl<I, O, S> ToScalarValueCall<S> for fn(I) -> O
145+
where
146+
S: ScalarValue,
147+
O: Display,
148+
{
149+
type Input = I;
150+
151+
fn __to_scalar_value_call(&self, input: Self::Input) -> S {
152+
S::from_display(&self(input))
153+
}
154+
}

0 commit comments

Comments
 (0)