|
1 | | -use std::{borrow::Cow, fmt}; |
| 1 | +use std::{ |
| 2 | + any::{Any, TypeId}, |
| 3 | + borrow::Cow, |
| 4 | + fmt, ptr, |
| 5 | +}; |
2 | 6 |
|
3 | 7 | use derive_more::with_trait::From; |
4 | 8 | use serde::{Serialize, de::DeserializeOwned}; |
@@ -223,8 +227,44 @@ pub trait ScalarValue: |
223 | 227 | unreachable!("`ScalarValue` must represent at least one of the GraphQL spec types") |
224 | 228 | } |
225 | 229 | } |
| 230 | + |
| 231 | + /// Creates this [`ScalarValue`] from the provided custom string type. |
| 232 | + /// |
| 233 | + /// This method should be implemented if [`ScalarValue`] implementation uses some custom string |
| 234 | + /// type inside to enable efficient conversion from values of this type. |
| 235 | + /// |
| 236 | + /// Default implementation allocates by converting [`ToString`] and [`From`]`<`[`String`]`>`. |
| 237 | + fn from_custom_string<Str: fmt::Display + Any + ?Sized>(s: &Str) -> Self { |
| 238 | + s.to_string().into() |
| 239 | + } |
226 | 240 | } |
227 | 241 |
|
| 242 | +/// Extension of [`Any`] for using its methods directly on the value without `dyn`. |
| 243 | +pub trait AnyExt: Any { |
| 244 | + /// Returns `true` if the this type is the same as `T`. |
| 245 | + #[must_use] |
| 246 | + fn is<T: Any + ?Sized>(&self) -> bool { |
| 247 | + TypeId::of::<T>() == self.type_id() |
| 248 | + } |
| 249 | + |
| 250 | + /// Returns [`Some`] reference to this value if it's of type `T`, or [`None`] otherwise. |
| 251 | + #[must_use] |
| 252 | + fn downcast_ref<T: Any>(&self) -> Option<&T> { |
| 253 | + self.is::<T>() |
| 254 | + .then(|| unsafe { &*(ptr::from_ref(self) as *const T) }) |
| 255 | + } |
| 256 | + |
| 257 | + /// Returns [`Some`] mutable reference to this value if it's of type `T`, or [`None`] otherwise. |
| 258 | + #[must_use] |
| 259 | + fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { |
| 260 | + // `self.is::<T>()` produces a false positive here: borrowed data escapes outside of method |
| 261 | + (TypeId::of::<Self>() == TypeId::of::<T>()) |
| 262 | + .then(|| unsafe { &mut *(ptr::from_mut(self) as *mut T) }) |
| 263 | + } |
| 264 | +} |
| 265 | + |
| 266 | +impl<T: Any + ?Sized> AnyExt for T {} |
| 267 | + |
228 | 268 | /// The default [`ScalarValue`] representation in [`juniper`]. |
229 | 269 | /// |
230 | 270 | /// These types closely follow the [GraphQL specification][0]. |
|
0 commit comments