Path: blob/main/crates/bevy_reflect/src/func/args/arg.rs
6600 views
use crate::{1func::args::{ArgError, FromArg, Ownership},2PartialReflect, Reflect, TypePath,3};4use alloc::{boxed::Box, string::ToString};5use core::ops::Deref;67/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].8///9/// [`DynamicFunction`]: crate::func::DynamicFunction10/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut11#[derive(Debug)]12pub struct Arg<'a> {13index: usize,14value: ArgValue<'a>,15}1617impl<'a> Arg<'a> {18/// Create a new [`Arg`] with the given index and value.19pub fn new(index: usize, value: ArgValue<'a>) -> Self {20Self { index, value }21}2223/// The index of the argument.24pub fn index(&self) -> usize {25self.index26}2728/// Set the index of the argument.29pub(crate) fn set_index(&mut self, index: usize) {30self.index = index;31}3233/// The value of the argument.34pub fn value(&self) -> &ArgValue<'a> {35&self.value36}3738/// Take the value of the argument.39pub fn take_value(self) -> ArgValue<'a> {40self.value41}4243/// Take the value of the argument and attempt to convert it to a concrete value, `T`.44///45/// This is a convenience method for calling [`FromArg::from_arg`] on the argument.46///47/// # Example48///49/// ```50/// # use bevy_reflect::func::ArgList;51/// let a = 1u32;52/// let b = 2u32;53/// let mut c = 3u32;54/// let mut args = ArgList::new().with_owned(a).with_ref(&b).with_mut(&mut c);55///56/// let a = args.take::<u32>().unwrap();57/// assert_eq!(a, 1);58///59/// let b = args.take::<&u32>().unwrap();60/// assert_eq!(*b, 2);61///62/// let c = args.take::<&mut u32>().unwrap();63/// assert_eq!(*c, 3);64/// ```65pub fn take<T: FromArg>(self) -> Result<T::This<'a>, ArgError> {66T::from_arg(self)67}6869/// Returns `Ok(T)` if the argument is [`ArgValue::Owned`].70///71/// If the argument is not owned, returns an error.72///73/// It's generally preferred to use [`Self::take`] instead of this method.74///75/// # Example76///77/// ```78/// # use bevy_reflect::func::ArgList;79/// let value = 123u32;80/// let mut args = ArgList::new().with_owned(value);81/// let value = args.take_owned::<u32>().unwrap();82/// assert_eq!(value, 123);83/// ```84pub fn take_owned<T: Reflect + TypePath>(self) -> Result<T, ArgError> {85match self.value {86ArgValue::Owned(arg) => arg.try_take().map_err(|arg| ArgError::UnexpectedType {87index: self.index,88expected: alloc::borrow::Cow::Borrowed(T::type_path()),89received: alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string()),90}),91ArgValue::Ref(_) => Err(ArgError::InvalidOwnership {92index: self.index,93expected: Ownership::Owned,94received: Ownership::Ref,95}),96ArgValue::Mut(_) => Err(ArgError::InvalidOwnership {97index: self.index,98expected: Ownership::Owned,99received: Ownership::Mut,100}),101}102}103104/// Returns `Ok(&T)` if the argument is [`ArgValue::Ref`].105///106/// If the argument is not a reference, returns an error.107///108/// It's generally preferred to use [`Self::take`] instead of this method.109///110/// # Example111///112/// ```113/// # use bevy_reflect::func::ArgList;114/// let value = 123u32;115/// let mut args = ArgList::new().with_ref(&value);116/// let value = args.take_ref::<u32>().unwrap();117/// assert_eq!(*value, 123);118/// ```119pub fn take_ref<T: Reflect + TypePath>(self) -> Result<&'a T, ArgError> {120match self.value {121ArgValue::Owned(_) => Err(ArgError::InvalidOwnership {122index: self.index,123expected: Ownership::Ref,124received: Ownership::Owned,125}),126ArgValue::Ref(arg) => {127Ok(arg128.try_downcast_ref()129.ok_or_else(|| ArgError::UnexpectedType {130index: self.index,131expected: alloc::borrow::Cow::Borrowed(T::type_path()),132received: alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string()),133})?)134}135ArgValue::Mut(_) => Err(ArgError::InvalidOwnership {136index: self.index,137expected: Ownership::Ref,138received: Ownership::Mut,139}),140}141}142143/// Returns `Ok(&mut T)` if the argument is [`ArgValue::Mut`].144///145/// If the argument is not a mutable reference, returns an error.146///147/// It's generally preferred to use [`Self::take`] instead of this method.148///149/// # Example150///151/// ```152/// # use bevy_reflect::func::ArgList;153/// let mut value = 123u32;154/// let mut args = ArgList::new().with_mut(&mut value);155/// let value = args.take_mut::<u32>().unwrap();156/// assert_eq!(*value, 123);157/// ```158pub fn take_mut<T: Reflect + TypePath>(self) -> Result<&'a mut T, ArgError> {159match self.value {160ArgValue::Owned(_) => Err(ArgError::InvalidOwnership {161index: self.index,162expected: Ownership::Mut,163received: Ownership::Owned,164}),165ArgValue::Ref(_) => Err(ArgError::InvalidOwnership {166index: self.index,167expected: Ownership::Mut,168received: Ownership::Ref,169}),170ArgValue::Mut(arg) => {171let received = alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string());172Ok(arg173.try_downcast_mut()174.ok_or_else(|| ArgError::UnexpectedType {175index: self.index,176expected: alloc::borrow::Cow::Borrowed(T::type_path()),177received,178})?)179}180}181}182183/// Returns `true` if the argument is of type `T`.184pub fn is<T: TypePath>(&self) -> bool {185self.value186.try_as_reflect()187.map(<dyn Reflect>::is::<T>)188.unwrap_or_default()189}190}191192/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].193///194/// [`DynamicFunction`]: crate::func::DynamicFunction195/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut196#[derive(Debug)]197pub enum ArgValue<'a> {198/// An owned argument.199Owned(Box<dyn PartialReflect>),200/// An immutable reference argument.201Ref(&'a dyn PartialReflect),202/// A mutable reference argument.203Mut(&'a mut dyn PartialReflect),204}205206impl<'a> Deref for ArgValue<'a> {207type Target = dyn PartialReflect;208209fn deref(&self) -> &Self::Target {210match self {211ArgValue::Owned(arg) => arg.as_ref(),212ArgValue::Ref(arg) => *arg,213ArgValue::Mut(arg) => *arg,214}215}216}217218219