Skip to content

Commit 1226536

Browse files
committed
Something that works
1 parent 46e7b2c commit 1226536

File tree

6 files changed

+96
-59
lines changed

6 files changed

+96
-59
lines changed

juniper/src/integrations/bigdecimal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ mod bigdecimal_scalar {
5454
.map_err(|e| format!("Failed to parse `BigDecimal` from `Float`: {e}").into())
5555
} else {
5656
v.try_to::<&str>()
57-
.map_err(|e| e.to_string().into())
57+
.map_err(|e| e.message().into())
5858
.and_then(|s| {
5959
BigDecimal::from_str(s).map_err(|e| {
6060
format!("Failed to parse `BigDecimal` from `String`: {e}").into()

juniper/src/integrations/rust_decimal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ mod rust_decimal_scalar {
4848
.map_err(|e| format!("Failed to parse `Decimal` from `Float`: {e}").into())
4949
} else {
5050
v.try_to::<&str>()
51-
.map_err(|e| e.to_string().into())
51+
.map_err(|e| e.message().into())
5252
.and_then(|s| {
5353
Decimal::from_str(s)
5454
.map_err(|e| format!("Failed to parse `Decimal` from `String`: {e}").into())

juniper/src/types/pointers.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ where
8787
}
8888
}
8989

90-
impl<T, S> FromScalarValue<S> for Box<T>
90+
impl<'s, T, S> FromScalarValue<'s, S> for Box<T>
9191
where
9292
S: ScalarValue,
93-
T: FromScalarValue<S>,
93+
T: FromScalarValue<'s, S> + 's,
9494
{
95-
fn from_scalar_value(v: &S) -> FieldResult<Self, S> {
96-
<T as FromScalarValue<S>>::from_scalar_value(v).map(Self::new)
95+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S> {
96+
T::from_scalar_value(v).map(Self::new)
9797
}
9898
}
9999

@@ -285,13 +285,13 @@ where
285285
}
286286
}
287287

288-
impl<T, S> FromScalarValue<S> for Arc<T>
288+
impl<'s, T, S> FromScalarValue<'s, S> for Arc<T>
289289
where
290290
S: ScalarValue,
291-
T: FromScalarValue<S>,
291+
T: FromScalarValue<'s, S> + 's,
292292
{
293-
fn from_scalar_value(v: &S) -> FieldResult<Self, S> {
294-
<T as FromScalarValue<S>>::from_scalar_value(v).map(Self::new)
293+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S> {
294+
T::from_scalar_value(v).map(Self::new)
295295
}
296296
}
297297

juniper/src/types/scalars.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use derive_more::with_trait::{Deref, Display, From, Into};
44
use serde::{Deserialize, Serialize};
55

66
use crate::{
7-
IntoFieldError,FieldResult, GraphQLScalar, Scalar,
7+
FieldResult, GraphQLScalar, IntoFieldError, Scalar,
88
ast::{InputValue, Selection, ToInputValue},
99
executor::{ExecutionResult, Executor, Registry},
1010
graphql_scalar,
@@ -16,7 +16,10 @@ use crate::{
1616
base::{GraphQLType, GraphQLValue},
1717
subscriptions::GraphQLSubscriptionValue,
1818
},
19-
value::{FromScalarValue, ParseScalarResult, ScalarValue, Value, WrongInputScalarTypeError},
19+
value::{
20+
FromScalarValue, ParseScalarResult, ScalarValue, TryScalarValueTo, Value,
21+
WrongInputScalarTypeError,
22+
},
2023
};
2124

2225
/// An ID as defined by the GraphQL specification
@@ -56,7 +59,7 @@ impl ID {
5659
}
5760

5861
#[graphql_scalar]
59-
#[graphql(with = impl_string_scalar, from_input_with = identity::<String>)]
62+
#[graphql(with = impl_string_scalar, from_input_with = __builtin)]
6063
type String = std::string::String;
6164

6265
mod impl_string_scalar {
@@ -170,21 +173,22 @@ where
170173
})
171174
}
172175

176+
173177
#[graphql_scalar]
174178
#[graphql(name = "String", with = impl_arcstr_scalar, parse_token(String))]
175179
type ArcStr = arcstr::ArcStr;
176180

177181
mod impl_arcstr_scalar {
178182
use super::ArcStr;
179-
use crate::{IntoValue as _, Scalar, ScalarValue, TryScalarValueTo, Value};
183+
use crate::{IntoValue as _, Scalar, ScalarValue, Value, FieldResult};
180184

181185
pub(super) fn to_output<S: ScalarValue>(v: &ArcStr) -> Value<S> {
182186
v.into_value()
183187
}
184-
188+
185189
pub(super) fn from_input<S: ScalarValue>(
186190
v: &Scalar<S>,
187-
) -> Result<ArcStr, <S as TryScalarValueTo<'_, &str>>::Error> {
191+
) -> FieldResult<ArcStr, S> {
188192
if let Some(s) = v.downcast_type::<ArcStr>() {
189193
Ok(s.clone())
190194
} else {
@@ -199,15 +203,15 @@ type CompactString = compact_str::CompactString;
199203

200204
mod impl_compactstring_scalar {
201205
use super::CompactString;
202-
use crate::{IntoValue as _, Scalar, ScalarValue, TryScalarValueTo, Value};
206+
use crate::{IntoValue as _, Scalar, ScalarValue, FieldResult, Value};
203207

204208
pub(super) fn to_output<S: ScalarValue>(v: &CompactString) -> Value<S> {
205209
v.into_value()
206210
}
207211

208212
pub(super) fn from_input<S: ScalarValue>(
209213
v: &Scalar<S>,
210-
) -> Result<CompactString, <S as TryScalarValueTo<'_, &str>>::Error> {
214+
) -> FieldResult<CompactString, S> {
211215
if let Some(s) = v.downcast_type::<CompactString>() {
212216
Ok(s.clone())
213217
} else {
@@ -286,8 +290,18 @@ where
286290
}
287291
}
288292

293+
impl<'s, S> FromScalarValue<'s, S> for &'s str
294+
where
295+
S: TryScalarValueTo<'s, Self, Error: IntoFieldError<S>> + 's,
296+
{
297+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S> {
298+
v.try_scalar_value_to()
299+
.map_err(IntoFieldError::into_field_error)
300+
}
301+
}
302+
289303
#[graphql_scalar]
290-
#[graphql(with = impl_boolean_scalar, from_input_with = identity::<Boolean>)]
304+
#[graphql(with = impl_boolean_scalar, from_input_with = __builtin)]
291305
type Boolean = bool;
292306

293307
mod impl_boolean_scalar {
@@ -304,7 +318,7 @@ mod impl_boolean_scalar {
304318
}
305319

306320
#[graphql_scalar]
307-
#[graphql(with = impl_int_scalar, from_input_with = identity::<Int>)]
321+
#[graphql(with = impl_int_scalar, from_input_with = __builtin)]
308322
type Int = i32;
309323

310324
mod impl_int_scalar {
@@ -326,7 +340,7 @@ mod impl_int_scalar {
326340
}
327341

328342
#[graphql_scalar]
329-
#[graphql(with = impl_float_scalar, from_input_with = identity::<Float>)]
343+
#[graphql(with = impl_float_scalar, from_input_with = __builtin)]
330344
type Float = f64;
331345

332346
mod impl_float_scalar {

juniper/src/value/scalar.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,14 @@ pub trait ScalarValue:
248248
///
249249
/// ```rust
250250
/// # use arcstr::ArcStr;
251-
/// # use juniper::{GraphQLScalar, Scalar, ScalarValue, TryScalarValueTo, Value};
251+
/// # use juniper::{FieldResult, GraphQLScalar, Scalar, ScalarValue, TryScalarValueTo, Value};
252252
/// #
253253
/// #[derive(GraphQLScalar)]
254254
/// #[graphql(from_input_with = Self::from_input, transparent)]
255255
/// struct Name(ArcStr);
256256
///
257257
/// impl Name {
258-
/// fn from_input<S: ScalarValue>(
259-
/// v: &Scalar<S>,
260-
/// ) -> Result<Self, <S as TryScalarValueTo<'_, &str>>::Error> {
258+
/// fn from_input<S: ScalarValue>(v: &Scalar<S>) -> FieldResult<Self, S> {
261259
/// // Check if our `ScalarValue` is represented by an `ArcStr` already, and if so,
262260
/// // do the cheap `Clone` instead of allocating a new `ArcStr` in its `From<&str>`
263261
/// // implementation.
@@ -302,12 +300,11 @@ pub trait ScalarValue:
302300
///
303301
/// Implementations should not implement this method, but rather implement the
304302
/// [`TryScalarValueTo<T>`] conversion directly.
305-
fn try_to<'a, T>(&'a self) -> Result<T, <Self as TryScalarValueTo<'a, Scalar<T>>>::Error>
303+
fn try_to<'a, T>(&'a self) -> FieldResult<T, Self>
306304
where
307-
T: 'a,
308-
Self: TryScalarValueTo<'a, Scalar<T>, Error: IntoFieldError<Self>>,
305+
T: FromScalarValue<'a, Self> + 'a,
309306
{
310-
self.try_scalar_value_to().map(|s: Scalar<T>| s.0)
307+
T::from_scalar_value(self)
311308
}
312309

313310
/// Tries to represent this [`ScalarValue`] as a [`bool`] value.
@@ -324,7 +321,7 @@ pub trait ScalarValue:
324321
/// [`TryScalarValueTo<bool>`] conversions for all the supported boolean types.
325322
#[must_use]
326323
fn try_to_bool(&self) -> Option<bool> {
327-
self.try_to().ok()
324+
self.try_scalar_value_to().ok()
328325
}
329326

330327
/// Tries to represent this [`ScalarValue`] as an [`i32`] value.
@@ -342,7 +339,7 @@ pub trait ScalarValue:
342339
/// less to an integer, if requested.
343340
#[must_use]
344341
fn try_to_int(&self) -> Option<i32> {
345-
self.try_to().ok()
342+
self.try_scalar_value_to().ok()
346343
}
347344

348345
/// Tries to represent this [`ScalarValue`] as a [`f64`] value.
@@ -360,7 +357,7 @@ pub trait ScalarValue:
360357
/// all floating point values with 64 bit or less to a float, if requested.
361358
#[must_use]
362359
fn try_to_float(&self) -> Option<f64> {
363-
self.try_to().ok()
360+
self.try_scalar_value_to().ok()
364361
}
365362

366363
/// Tries to represent this [`ScalarValue`] as a [`String`] value.
@@ -380,7 +377,7 @@ pub trait ScalarValue:
380377
/// [`TryScalarValueTo<String>`] conversions for all the supported string types, if requested.
381378
#[must_use]
382379
fn try_to_string(&self) -> Option<String> {
383-
self.try_to().ok()
380+
self.try_scalar_value_to().ok()
384381
}
385382

386383
/// Tries to convert this [`ScalarValue`] into a [`String`] value.
@@ -417,7 +414,7 @@ pub trait ScalarValue:
417414
/// requested.
418415
#[must_use]
419416
fn try_as_str(&self) -> Option<&str> {
420-
self.try_to().ok()
417+
self.try_scalar_value_to().ok()
421418
}
422419

423420
/// Converts this [`ScalarValue`] into another one via [`i32`], [`f64`], [`bool`] or [`String`]
@@ -496,25 +493,33 @@ impl<'me, S: ScalarValue> TryScalarValueTo<'me, &'me Scalar<S>> for S {
496493
}
497494
}
498495

499-
impl<'me, S: ScalarValue> TryScalarValueTo<'me, Scalar<&'me str>> for S {
496+
impl<'me, T, S> TryScalarValueTo<'me, Scalar<T>> for S
497+
where
498+
T: FromScalarValue<'me, S> + 'me,
499+
S: ScalarValue,
500+
{
500501
type Error = FieldError<Self>;
501502

502-
fn try_scalar_value_to(&'me self) -> FieldResult<Scalar<&'me str>, Self> {
503-
self.try_scalar_value_to().map(Scalar)
503+
fn try_scalar_value_to(&'me self) -> FieldResult<Scalar<T>, Self> {
504+
T::from_scalar_value(self).map(Scalar)
504505
}
505506
}
506507

507-
impl<'me, T: FromScalarValue<S> + 'me, S: ScalarValue> TryScalarValueTo<'me, Scalar<T>> for S {
508-
type Error = FieldError<Self>;
508+
pub trait FromScalarValue<'s, S: 's = DefaultScalarValue>: Sized {
509+
/// Performs the conversion.
510+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S>;
511+
}
509512

510-
fn try_scalar_value_to(&'me self) -> FieldResult<Scalar<T>, Self> {
511-
T::from_scalar_value(self).map(Scalar)
513+
impl<'s, S> FromScalarValue<'s, S> for &'s S {
514+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S> {
515+
Ok(v)
512516
}
513517
}
514518

515-
pub trait FromScalarValue<S = DefaultScalarValue>: Sized {
516-
/// Performs the conversion.
517-
fn from_scalar_value(v: &S) -> FieldResult<Self, S>;
519+
impl<'s, S> FromScalarValue<'s, S> for &'s Scalar<S> {
520+
fn from_scalar_value(v: &'s S) -> FieldResult<Self, S> {
521+
Ok(Scalar::ref_cast(v))
522+
}
518523
}
519524

520525
/// Error of a [`ScalarValue`] not matching the expected type.

juniper_codegen/src/graphql_scalar/mod.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -495,41 +495,59 @@ impl Definition {
495495
fn impl_from_scalar_value_tokens(&self) -> TokenStream {
496496
let scalar = &self.scalar;
497497

498-
let (ty, generics) = self.impl_self_and_generics(false);
499-
let (impl_gens, _, where_clause) = generics.split_for_impl();
498+
let ref_lt = quote! { '___a };
499+
let (ty, mut generics) = self.impl_self_and_generics(false);
500+
generics.params.push(parse_quote! { #ref_lt });
501+
generics.make_where_clause().predicates.push(parse_quote! {
502+
Self: #ref_lt
503+
});
500504

501505
let body = match &self.methods {
502506
Methods::Custom { from_input, .. }
503507
| Methods::Delegated {
504508
from_input: Some(from_input),
505509
..
506510
} => {
507-
quote! {
508-
use ::juniper::macros::helper::ToResultCall as _;
509-
510-
let input = ::juniper::TryScalarValueTo::try_scalar_value_to(input)
511-
.map_err(::juniper::executor::IntoFieldError::<#scalar>::into_field_error)?;
512-
let func: fn(_) -> _ = #from_input;
513-
(&&func)
514-
.__to_result_call(input)
515-
.map_err(::juniper::executor::IntoFieldError::<#scalar>::into_field_error)
511+
if from_input == &parse_quote! { __builtin } {
512+
quote! {
513+
::juniper::TryScalarValueTo::try_scalar_value_to(input)
514+
.map_err(::juniper::executor::IntoFieldError::<#scalar>::into_field_error)
515+
}
516+
} else {
517+
quote! {
518+
use ::juniper::macros::helper::ToResultCall as _;
519+
520+
let input = ::juniper::ScalarValue::try_to(input)?;
521+
let func: fn(_) -> _ = #from_input;
522+
(&&func)
523+
.__to_result_call(input)
524+
.map_err(::juniper::executor::IntoFieldError::<#scalar>::into_field_error)
525+
}
516526
}
517527
}
518528
Methods::Delegated { field, .. } => {
519529
let field_ty = field.ty();
520530
let self_constructor = field.closure_constructor();
521531

532+
generics.make_where_clause().predicates.push(parse_quote! {
533+
#field_ty: ::juniper::FromScalarValue<#ref_lt, #scalar>
534+
});
535+
522536
quote! {
523-
<#field_ty as ::juniper::FromScalarValue<#scalar>>::from_scalar_value(input)
524-
.map(#self_constructor)
537+
<#field_ty as ::juniper::FromScalarValue<#ref_lt, #scalar>>
538+
::from_scalar_value(input).map(#self_constructor)
525539
}
526540
}
527541
};
528542

543+
let (lt_impl_gens, _, where_clause) = generics.split_for_impl();
544+
529545
quote! {
530546
#[automatically_derived]
531-
impl #impl_gens ::juniper::FromScalarValue<#scalar> for #ty #where_clause {
532-
fn from_scalar_value(input: &#scalar) -> ::juniper::FieldResult<Self, #scalar> {
547+
impl #lt_impl_gens ::juniper::FromScalarValue<#ref_lt, #scalar> for #ty #where_clause {
548+
fn from_scalar_value(
549+
input: &#ref_lt #scalar,
550+
) -> ::juniper::FieldResult<Self, #scalar> {
533551
#body
534552
}
535553
}

0 commit comments

Comments
 (0)