@@ -247,42 +247,95 @@ pub trait ScalarValue:
247247 ///
248248 /// ```rust
249249 /// # use arcstr::ArcStr;
250- /// # use juniper::{FromScalarValue , GraphQLScalar, Scalar, ScalarValue, TryScalarValueTo, Value};
250+ /// # use juniper::{FieldResult , GraphQLScalar, Scalar, ScalarValue, TryScalarValueTo, Value};
251251 /// #
252252 /// #[derive(GraphQLScalar)]
253253 /// #[graphql(from_input_with = Self::from_input, transparent)]
254254 /// struct Name(ArcStr);
255255 ///
256256 /// impl Name {
257- /// fn from_input<S: ScalarValue>(
258- /// v: &Scalar<S>,
259- /// ) -> Result<Self, <&str as FromScalarValue<S>>::Error> {
257+ /// fn from_input<S: ScalarValue>(v: &Scalar<S>) -> FieldResult<Self, S> {
260258 /// // Check if our `ScalarValue` is represented by an `ArcStr` already, and if so,
261259 /// // do the cheap `Clone` instead of allocating a new `ArcStr` in its `From<&str>`
262260 /// // implementation.
263- /// if let Some(s) = v.downcast_type::<ArcStr>() {
264- /// Ok(Self( s.clone()) )
261+ /// let s = if let Some(s) = v.downcast_type::<ArcStr>() {
262+ /// s.clone()
265263 /// } else {
266- /// v.try_to::<&str>().map(|s| Self(s.into()))
264+ /// v.try_to::<&str>().map(ArcStr::from)?
265+ /// };
266+ /// if s.chars().next().is_some_and(char::is_uppercase) {
267+ /// Ok(Self(s))
268+ /// } else {
269+ /// Err("`Name` should start with a capital letter".into())
270+ /// }
271+ /// }
272+ /// }
273+ /// ```
274+ ///
275+ /// However, this method is needed only when the type doesn't implement a [`GraphQLScalar`]
276+ /// itself, or does it in non-optimal way. In reality, the [`ArcStr`] already implements a
277+ /// [`GraphQLScalar`] and does the [`ScalarValue::downcast_type()`] check in its implementation,
278+ /// which can be naturally reused by calling the [`ScalarValue::try_to()`] method.
279+ ///
280+ /// ```rust
281+ /// # use arcstr::ArcStr;
282+ /// # use juniper::{FieldResult, GraphQLScalar, Scalar, ScalarValue, TryScalarValueTo, Value};
283+ /// #
284+ /// #[derive(GraphQLScalar)]
285+ /// #[graphql(from_input_with = Self::from_input, transparent)]
286+ /// struct Name(ArcStr);
287+ ///
288+ /// impl Name {
289+ /// fn from_input(s: ArcStr) -> Result<Self, &'static str> {
290+ /// // ^^^^^^ macro expansion will call the `ScalarValue::try_to()` method
291+ /// // to extract this type from the `ScalarValue` to this function
292+ /// if s.chars().next().is_some_and(char::is_uppercase) {
293+ /// Ok(Self(s))
294+ /// } else {
295+ /// Err("`Name` should start with a capital letter")
267296 /// }
268297 /// }
269298 /// }
270299 /// ```
271300 #[ must_use]
272301 fn downcast_type < T : Any > ( & self ) -> Option < & T > ;
273-
274- /// TODO: renew docs
302+
275303 /// Tries to represent this [`ScalarValue`] as the specified type `T`.
276- ///
277- /// This method could be used instead of other helpers in case the [`TryScalarValueTo::Error`]
278- /// is needed.
304+ ///
305+ /// This method is the recommended way to parse a defined [`GraphQLScalar`] type `T` from a
306+ /// [`ScalarValue`].
307+ ///
308+ /// This method could be used instead of other `try_*` helpers in case the
309+ /// [`FromScalarValue::Error`] is needed.
310+ ///
311+ /// # Example
312+ ///
313+ /// ```rust
314+ /// # use juniper::{DefaultScalarValue, GraphQLScalar, ScalarValue as _};
315+ ///
316+ /// let v = DefaultScalarValue::Boolean(false);
317+ /// assert_eq!(v.try_to::<bool>().unwrap(), false);
318+ /// assert!(v.try_to::<f64>().is_err());
319+ ///
320+ /// #[derive(Debug, GraphQLScalar, PartialEq)]
321+ /// #[graphql(transparent)]
322+ /// struct Name(String);
323+ ///
324+ /// let v = DefaultScalarValue::String("John".into());
325+ /// assert_eq!(v.try_to::<String>().unwrap(), "John");
326+ /// assert_eq!(v.try_to::<&str>().unwrap(), "John");
327+ /// assert_eq!(v.try_to::<Name>().unwrap(), Name("John".into()));
328+ /// assert!(v.try_to::<i32>().is_err());
329+ /// ```
279330 ///
280331 /// # Implementation
281332 ///
282- /// This method is an ergonomic alias for the [`TryScalarValueTo <T>`] conversion.
333+ /// This method is an ergonomic alias for the [`FromScalarValue <T>`] conversion.
283334 ///
284- /// Implementations should not implement this method, but rather implement the
285- /// [`TryScalarValueTo<T>`] conversion directly.
335+ /// Implementations should not implement this method, but rather implement only the
336+ /// [`TryScalarValueTo<T>`] conversion directly in case `T` is a primitive built-in GraphQL
337+ /// scalar type ([`bool`], [`f64`], [`i32`], [`&str`], or [`String`]), otherwise the
338+ /// [`FromScalarValue<T>`] conversion is provided when a [`GraphQLScalar`] is implemented.
286339 fn try_to < ' a , T > ( & ' a self ) -> Result < T , T :: Error >
287340 where
288341 T : FromScalarValue < ' a , Self > + ' a ,
0 commit comments