Commit b4774d23 authored by Mathias Svensson's avatar Mathias Svensson Committed by Robert Winslow

Rust: Fix Copy and Clone impls for a few generic types (#5577)

* Rust: Fix Copy and Clone impls for a few generic types

* Add tests for Copy+Clone

* Wrap Copy+Clone checks in a #[test] function
parent 26f238c2
...@@ -79,9 +79,21 @@ pub struct VTableWIPOffset {} ...@@ -79,9 +79,21 @@ pub struct VTableWIPOffset {}
/// data relative to the *end* of an in-progress FlatBuffer. The /// data relative to the *end* of an in-progress FlatBuffer. The
/// FlatBufferBuilder uses this to track the location of objects in an absolute /// FlatBufferBuilder uses this to track the location of objects in an absolute
/// way. The impl of Push converts a WIPOffset into a ForwardsUOffset. /// way. The impl of Push converts a WIPOffset into a ForwardsUOffset.
#[derive(Debug, Clone, Copy)] #[derive(Debug)]
pub struct WIPOffset<T>(UOffsetT, PhantomData<T>); pub struct WIPOffset<T>(UOffsetT, PhantomData<T>);
// We cannot use derive for these two impls, as the derived impls would only
// implement `Copy` and `Clone` for `T: Copy` and `T: Clone` respectively.
// However `WIPOffset<T>` can always be copied, no matter that `T` you
// have.
impl<T> Copy for WIPOffset<T> {}
impl<T> Clone for WIPOffset<T> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> PartialEq for WIPOffset<T> { impl<T> PartialEq for WIPOffset<T> {
fn eq(&self, o: &WIPOffset<T>) -> bool { fn eq(&self, o: &WIPOffset<T>) -> bool {
self.value() == o.value() self.value() == o.value()
...@@ -108,12 +120,12 @@ impl<'a, T: 'a> WIPOffset<T> { ...@@ -108,12 +120,12 @@ impl<'a, T: 'a> WIPOffset<T> {
/// Return a wrapped value that brings its meaning as a union WIPOffset /// Return a wrapped value that brings its meaning as a union WIPOffset
/// into the type system. /// into the type system.
#[inline(always)] #[inline(always)]
pub fn as_union_value(&self) -> WIPOffset<UnionWIPOffset> { pub fn as_union_value(self) -> WIPOffset<UnionWIPOffset> {
WIPOffset::new(self.0) WIPOffset::new(self.0)
} }
/// Get the underlying value. /// Get the underlying value.
#[inline(always)] #[inline(always)]
pub fn value(&self) -> UOffsetT { pub fn value(self) -> UOffsetT {
self.0 self.0
} }
} }
...@@ -139,11 +151,24 @@ impl<T> Push for ForwardsUOffset<T> { ...@@ -139,11 +151,24 @@ impl<T> Push for ForwardsUOffset<T> {
/// ForwardsUOffset is used by Follow to traverse a FlatBuffer: the pointer /// ForwardsUOffset is used by Follow to traverse a FlatBuffer: the pointer
/// is incremented by the value contained in this type. /// is incremented by the value contained in this type.
#[derive(Debug, Clone, Copy)] #[derive(Debug)]
pub struct ForwardsUOffset<T>(UOffsetT, PhantomData<T>); pub struct ForwardsUOffset<T>(UOffsetT, PhantomData<T>);
// We cannot use derive for these two impls, as the derived impls would only
// implement `Copy` and `Clone` for `T: Copy` and `T: Clone` respectively.
// However `ForwardsUOffset<T>` can always be copied, no matter that `T` you
// have.
impl<T> Copy for ForwardsUOffset<T> {}
impl<T> Clone for ForwardsUOffset<T> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> ForwardsUOffset<T> { impl<T> ForwardsUOffset<T> {
#[inline(always)] #[inline(always)]
pub fn value(&self) -> UOffsetT { pub fn value(self) -> UOffsetT {
self.0 self.0
} }
} }
......
...@@ -25,9 +25,19 @@ use endian_scalar::{read_scalar, read_scalar_at}; ...@@ -25,9 +25,19 @@ use endian_scalar::{read_scalar, read_scalar_at};
use follow::Follow; use follow::Follow;
use primitives::*; use primitives::*;
#[derive(Debug, Clone, Copy)] #[derive(Debug)]
pub struct Vector<'a, T: 'a>(&'a [u8], usize, PhantomData<T>); pub struct Vector<'a, T: 'a>(&'a [u8], usize, PhantomData<T>);
// We cannot use derive for these two impls, as it would only implement Copy
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
// can always be copied, no matter that `T` you have.
impl<'a, T> Copy for Vector<'a, T> {}
impl<'a, T> Clone for Vector<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T: 'a> Vector<'a, T> { impl<'a, T: 'a> Vector<'a, T> {
#[inline(always)] #[inline(always)]
pub fn new(buf: &'a [u8], loc: usize) -> Self { pub fn new(buf: &'a [u8], loc: usize) -> Self {
......
...@@ -19,6 +19,7 @@ path = "bin/alloc_check.rs" ...@@ -19,6 +19,7 @@ path = "bin/alloc_check.rs"
quickcheck = "0.6" quickcheck = "0.6"
# TODO(rw): look into moving to criterion.rs # TODO(rw): look into moving to criterion.rs
bencher = "0.1.5" bencher = "0.1.5"
static_assertions = "1.0.0"
[[bench]] [[bench]]
# setup for bencher # setup for bencher
......
...@@ -2694,6 +2694,21 @@ mod byte_layouts { ...@@ -2694,6 +2694,21 @@ mod byte_layouts {
} }
} }
#[cfg(test)]
mod copy_clone_traits {
#[test]
fn follow_types_implement_copy_and_clone() {
static_assertions::assert_impl_all!(flatbuffers::WIPOffset<u32>: Copy, Clone);
static_assertions::assert_impl_all!(flatbuffers::WIPOffset<Vec<u32>>: Copy, Clone);
static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<u32>: Copy, Clone);
static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<Vec<u32>>: Copy, Clone);
static_assertions::assert_impl_all!(flatbuffers::Vector<'static, u32>: Copy, Clone);
static_assertions::assert_impl_all!(flatbuffers::Vector<'static, Vec<u32>>: Copy, Clone);
}
}
// this is not technically a test, but we want to always keep this generated // this is not technically a test, but we want to always keep this generated
// file up-to-date, and the simplest way to do that is to make sure that when // file up-to-date, and the simplest way to do that is to make sure that when
// tests are run, the file is generated. // tests are run, the file is generated.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment