@@ -8,6 +8,8 @@ use derive_more::with_trait::From;
88use serde:: { Serialize , de:: DeserializeOwned } ;
99
1010use crate :: parser:: { ParseError , ScalarToken } ;
11+ #[ cfg( doc) ]
12+ use crate :: { InputValue , Value } ;
1113
1214pub use juniper_codegen:: ScalarValue ;
1315
@@ -20,44 +22,68 @@ pub trait ParseScalarValue<S = DefaultScalarValue> {
2022 fn from_str ( value : ScalarToken < ' _ > ) -> ParseScalarResult < S > ;
2123}
2224
23- /// A trait marking a type that could be used as internal representation of
24- /// scalar values in juniper
25+ /// Type that could be used as internal representation of scalar values (e.g. inside [`Value`] and
26+ /// [`InputValue`]).
2527///
26- /// The main objective of this abstraction is to allow other libraries to
27- /// replace the default representation with something that better fits their
28- /// needs.
29- /// There is a custom derive (`#[derive(`[`ScalarValue`]`)]`) available that
30- /// implements most of the required traits automatically for a enum representing
31- /// a scalar value. However, [`Serialize`] and [`Deserialize`] implementations
28+ /// This abstraction allows other libraries and user code to replace the default representation with
29+ /// something that better fits their needs than [`DefaultScalarValue`].
30+ ///
31+ /// # Deriving
32+ ///
33+ /// There is a custom derive (`#[derive(`[`ScalarValue`](macro@crate::ScalarValue)`)]`) available,
34+ /// that implements most of the required traits automatically for an enum representing a
35+ /// [`ScalarValue`]. However, [`Serialize`] and [`Deserialize`] implementations
3236/// are expected to be provided.
3337///
34- /// # Implementing a new scalar value representation
35- /// The preferred way to define a new scalar value representation is
36- /// defining a enum containing a variant for each type that needs to be
37- /// represented at the lowest level.
38- /// The following example introduces an new variant that is able to store 64 bit
39- /// integers.
38+ /// # Example
39+ ///
40+ /// The preferred way to define a new [`ScalarValue`] representation is defining an enum containing
41+ /// a variant for each type that needs to be represented at the lowest level.
42+ ///
43+ /// The following example introduces a new variant that is able to store 64-bit integers, and uses
44+ /// a [`CompactString`] for a string representation.
4045///
4146/// ```rust
42- /// # use std::fmt;
47+ /// # use std::{any::Any, fmt} ;
4348/// #
44- /// # use serde::{de, Deserialize, Deserializer, Serialize} ;
49+ /// # use compact_str::CompactString ;
4550/// # use juniper::ScalarValue;
51+ /// # use serde::{de, Deserialize, Deserializer, Serialize};
4652/// #
4753/// #[derive(Clone, Debug, PartialEq, ScalarValue, Serialize)]
4854/// #[serde(untagged)]
55+ /// #[value(from_displayable_with = from_compact_str)]
4956/// enum MyScalarValue {
5057/// #[value(as_float, as_int)]
5158/// Int(i32),
5259/// Long(i64),
5360/// #[value(as_float)]
5461/// Float(f64),
5562/// #[value(as_str, as_string, into_string)]
56- /// String(String ),
63+ /// String(CompactString ),
5764/// #[value(as_bool)]
5865/// Boolean(bool),
5966/// }
6067///
68+ /// // Custom implementation of `ScalarValue::from_displayable()` method
69+ /// // for efficient conversions from `CompactString` into `MyScalarValue`.
70+ /// fn from_compact_str<Str: fmt::Display + Any + ?Sized>(s: &Str) -> MyScalarValue {
71+ /// use juniper::AnyExt as _; // allows downcasting directly on types without `dyn`
72+ ///
73+ /// if let Some(s) = s.downcast_ref::<CompactString>() {
74+ /// MyScalarValue::String(s.clone())
75+ /// } else {
76+ /// s.to_string().into()
77+ /// }
78+ /// }
79+ ///
80+ /// // Macro cannot infer and generate this impl if a custom string type is used.
81+ /// impl From<String> for MyScalarValue {
82+ /// fn from(value: String) -> Self {
83+ /// Self::String(value.into())
84+ /// }
85+ /// }
86+ ///
6187/// impl<'de> Deserialize<'de> for MyScalarValue {
6288/// fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
6389/// struct Visitor;
@@ -115,7 +141,7 @@ pub trait ParseScalarValue<S = DefaultScalarValue> {
115141/// }
116142///
117143/// fn visit_string<E: de::Error>(self, s: String) -> Result<Self::Value, E> {
118- /// Ok(MyScalarValue::String(s))
144+ /// Ok(MyScalarValue::String(s.into() ))
119145/// }
120146/// }
121147///
@@ -124,6 +150,7 @@ pub trait ParseScalarValue<S = DefaultScalarValue> {
124150/// }
125151/// ```
126152///
153+ /// [`CompactString`]: compact_str::CompactString
127154/// [`Deserialize`]: trait@serde::Deserialize
128155/// [`Serialize`]: trait@serde::Serialize
129156pub trait ScalarValue :
@@ -228,14 +255,18 @@ pub trait ScalarValue:
228255 }
229256 }
230257
231- /// Creates this [`ScalarValue`] from the provided custom string type.
258+ /// Creates this [`ScalarValue`] from the provided [`fmt::Display`] type.
232259 ///
233260 /// This method should be implemented if [`ScalarValue`] implementation uses some custom string
234261 /// type inside to enable efficient conversion from values of this type.
235262 ///
236263 /// Default implementation allocates by converting [`ToString`] and [`From`]`<`[`String`]`>`.
264+ ///
265+ /// # Example
266+ ///
267+ /// See the [example in trait documentation](ScalarValue#example) for how it can be used.
237268 #[ must_use]
238- fn from_custom_string < Str : fmt:: Display + Any + ?Sized > ( s : & Str ) -> Self {
269+ fn from_displayable < Str : fmt:: Display + Any + ?Sized > ( s : & Str ) -> Self {
239270 s. to_string ( ) . into ( )
240271 }
241272}
0 commit comments