Skip to content

Commit e6b655f

Browse files
EliasPrescottMinerSebasalice-i-cecile
authored
adding reflection for Cow<'static, [T]> (#7454)
# Objective - Implementing reflection for Cow<'static, [T]> - Hopefully fixes #7429 ## Solution - Implementing Reflect, Typed, GetTypeRegistration, and FromReflect for Cow<'static, [T]> --- ## Notes I have not used bevy_reflection much yet, so I may not fully understand all the use cases. This is also my first attempt at contributing, so I would appreciate any feedback or recommendations for changes. I tried to add cases for using Cow<'static, str> and Cow<'static, [u8]> to some of the bevy_reflect tests, but I can't guarantee those tests are comprehensive enough. --------- Co-authored-by: MinerSebas <[email protected]> Co-authored-by: Alice Cecile <[email protected]>
1 parent 28e9c52 commit e6b655f

File tree

2 files changed

+214
-2
lines changed

2 files changed

+214
-2
lines changed

crates/bevy_reflect/src/impls/std.rs

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,178 @@ impl FromReflect for Cow<'static, str> {
12191219
}
12201220
}
12211221

1222+
impl<T: PathOnly> PathOnly for [T] where [T]: ToOwned {}
1223+
1224+
impl<T: TypePath> TypePath for [T]
1225+
where
1226+
[T]: ToOwned,
1227+
{
1228+
fn type_path() -> &'static str {
1229+
static CELL: GenericTypePathCell = GenericTypePathCell::new();
1230+
CELL.get_or_insert::<Self, _>(|| format!("[{}]", <T>::type_path()))
1231+
}
1232+
1233+
fn short_type_path() -> &'static str {
1234+
static CELL: GenericTypePathCell = GenericTypePathCell::new();
1235+
CELL.get_or_insert::<Self, _>(|| format!("[{}]", <T>::short_type_path()))
1236+
}
1237+
}
1238+
1239+
impl<T: ToOwned> PathOnly for T {}
1240+
1241+
impl<T: FromReflect + Clone + TypePath> List for Cow<'static, [T]> {
1242+
fn get(&self, index: usize) -> Option<&dyn Reflect> {
1243+
self.as_ref().get(index).map(|x| x as &dyn Reflect)
1244+
}
1245+
1246+
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
1247+
self.to_mut().get_mut(index).map(|x| x as &mut dyn Reflect)
1248+
}
1249+
1250+
fn len(&self) -> usize {
1251+
self.as_ref().len()
1252+
}
1253+
1254+
fn iter(&self) -> crate::ListIter {
1255+
crate::ListIter::new(self)
1256+
}
1257+
1258+
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
1259+
// into_owned() is not uneccessary here because it avoids cloning whenever you have a Cow::Owned already
1260+
#[allow(clippy::unnecessary_to_owned)]
1261+
self.into_owned()
1262+
.into_iter()
1263+
.map(|value| value.clone_value())
1264+
.collect()
1265+
}
1266+
1267+
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {
1268+
let value = element.take::<T>().unwrap_or_else(|value| {
1269+
T::from_reflect(&*value).unwrap_or_else(|| {
1270+
panic!(
1271+
"Attempted to insert invalid value of type {}.",
1272+
value.type_name()
1273+
)
1274+
})
1275+
});
1276+
self.to_mut().insert(index, value);
1277+
}
1278+
1279+
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
1280+
Box::new(self.to_mut().remove(index))
1281+
}
1282+
1283+
fn push(&mut self, value: Box<dyn Reflect>) {
1284+
let value = T::take_from_reflect(value).unwrap_or_else(|value| {
1285+
panic!(
1286+
"Attempted to push invalid value of type {}.",
1287+
value.type_name()
1288+
)
1289+
});
1290+
self.to_mut().push(value);
1291+
}
1292+
1293+
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
1294+
self.to_mut()
1295+
.pop()
1296+
.map(|value| Box::new(value) as Box<dyn Reflect>)
1297+
}
1298+
}
1299+
1300+
impl<T: FromReflect + Clone + TypePath> Reflect for Cow<'static, [T]> {
1301+
fn type_name(&self) -> &str {
1302+
std::any::type_name::<Self>()
1303+
}
1304+
1305+
fn into_any(self: Box<Self>) -> Box<dyn Any> {
1306+
self
1307+
}
1308+
1309+
fn as_any(&self) -> &dyn Any {
1310+
self
1311+
}
1312+
1313+
fn as_any_mut(&mut self) -> &mut dyn Any {
1314+
self
1315+
}
1316+
1317+
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
1318+
self
1319+
}
1320+
1321+
fn as_reflect(&self) -> &dyn Reflect {
1322+
self
1323+
}
1324+
1325+
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
1326+
self
1327+
}
1328+
1329+
fn apply(&mut self, value: &dyn Reflect) {
1330+
crate::list_apply(self, value);
1331+
}
1332+
1333+
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
1334+
*self = value.take()?;
1335+
Ok(())
1336+
}
1337+
1338+
fn reflect_ref(&self) -> ReflectRef {
1339+
ReflectRef::List(self)
1340+
}
1341+
1342+
fn reflect_mut(&mut self) -> ReflectMut {
1343+
ReflectMut::List(self)
1344+
}
1345+
1346+
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
1347+
ReflectOwned::List(self)
1348+
}
1349+
1350+
fn clone_value(&self) -> Box<dyn Reflect> {
1351+
Box::new(List::clone_dynamic(self))
1352+
}
1353+
1354+
fn reflect_hash(&self) -> Option<u64> {
1355+
crate::list_hash(self)
1356+
}
1357+
1358+
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
1359+
crate::list_partial_eq(self, value)
1360+
}
1361+
1362+
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
1363+
Some(<Self as Typed>::type_info())
1364+
}
1365+
}
1366+
1367+
impl<T: FromReflect + Clone + TypePath> Typed for Cow<'static, [T]> {
1368+
fn type_info() -> &'static TypeInfo {
1369+
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
1370+
CELL.get_or_insert::<Self, _>(|| TypeInfo::List(ListInfo::new::<Self, T>()))
1371+
}
1372+
}
1373+
1374+
impl<T: FromReflect + Clone + TypePath> GetTypeRegistration for Cow<'static, [T]> {
1375+
fn get_type_registration() -> TypeRegistration {
1376+
TypeRegistration::of::<Cow<'static, [T]>>()
1377+
}
1378+
}
1379+
1380+
impl<T: FromReflect + Clone + TypePath> FromReflect for Cow<'static, [T]> {
1381+
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
1382+
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
1383+
let mut temp_vec = Vec::with_capacity(ref_list.len());
1384+
for field in ref_list.iter() {
1385+
temp_vec.push(T::from_reflect(field)?);
1386+
}
1387+
temp_vec.try_into().ok()
1388+
} else {
1389+
None
1390+
}
1391+
}
1392+
}
1393+
12221394
impl Reflect for &'static Path {
12231395
fn type_name(&self) -> &str {
12241396
std::any::type_name::<Self>()

crates/bevy_reflect/src/lib.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,12 @@ mod tests {
550550
ser::{to_string_pretty, PrettyConfig},
551551
Deserializer,
552552
};
553-
use std::fmt::{Debug, Formatter};
554-
use std::{any::TypeId, marker::PhantomData};
553+
use std::{
554+
any::TypeId,
555+
borrow::Cow,
556+
fmt::{Debug, Formatter},
557+
marker::PhantomData,
558+
};
555559

556560
use super::prelude::*;
557561
use super::*;
@@ -1031,6 +1035,8 @@ mod tests {
10311035
b: Bar,
10321036
u: usize,
10331037
t: ([f32; 3], String),
1038+
v: Cow<'static, str>,
1039+
w: Cow<'static, [u8]>,
10341040
}
10351041

10361042
let foo = Foo {
@@ -1039,6 +1045,8 @@ mod tests {
10391045
b: Bar { y: 255 },
10401046
u: 1111111111111,
10411047
t: ([3.0, 2.0, 1.0], "Tuple String".to_string()),
1048+
v: Cow::Owned("Cow String".to_string()),
1049+
w: Cow::Owned(vec![1, 2, 3]),
10421050
};
10431051

10441052
let foo2: Box<dyn Reflect> = Box::new(foo.clone());
@@ -1394,6 +1402,38 @@ mod tests {
13941402
let info = value.get_represented_type_info().unwrap();
13951403
assert!(info.is::<MyArray>());
13961404

1405+
// Cow<'static, str>
1406+
type MyCowStr = Cow<'static, str>;
1407+
1408+
let info = MyCowStr::type_info();
1409+
if let TypeInfo::Value(info) = info {
1410+
assert!(info.is::<MyCowStr>());
1411+
assert_eq!(std::any::type_name::<MyCowStr>(), info.type_name());
1412+
} else {
1413+
panic!("Expected `TypeInfo::Value`");
1414+
}
1415+
1416+
let value: &dyn Reflect = &Cow::<'static, str>::Owned("Hello!".to_string());
1417+
let info = value.get_represented_type_info().unwrap();
1418+
assert!(info.is::<MyCowStr>());
1419+
1420+
// Cow<'static, [u8]>
1421+
type MyCowSlice = Cow<'static, [u8]>;
1422+
1423+
let info = MyCowSlice::type_info();
1424+
if let TypeInfo::List(info) = info {
1425+
assert!(info.is::<MyCowSlice>());
1426+
assert!(info.item_is::<u8>());
1427+
assert_eq!(std::any::type_name::<MyCowSlice>(), info.type_name());
1428+
assert_eq!(std::any::type_name::<u8>(), info.item_type_name());
1429+
} else {
1430+
panic!("Expected `TypeInfo::List`");
1431+
}
1432+
1433+
let value: &dyn Reflect = &Cow::<'static, [u8]>::Owned(vec![0, 1, 2, 3]);
1434+
let info = value.get_represented_type_info().unwrap();
1435+
assert!(info.is::<MyCowSlice>());
1436+
13971437
// Map
13981438
type MyMap = HashMap<usize, f32>;
13991439

0 commit comments

Comments
 (0)