Skip to content

Commit d787869

Browse files
Make any &T impl AsView if T impl AsView
And same for &mut T if T impl AsMut This matches the behavior of std::convert::AsRef which has similar blanket impls to this. PiperOrigin-RevId: 883287790
1 parent 9b38d6d commit d787869

3 files changed

Lines changed: 125 additions & 1 deletion

File tree

rust/internal.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub struct Private;
4141
/// traits to support trait objects.
4242
pub trait SealedInternal: Sized {}
4343

44+
impl<T: SealedInternal> SealedInternal for &T {}
45+
impl<T: SealedInternal> SealedInternal for &mut T {}
46+
4447
/// A trait used by the proto_eq() gtest macro.
4548
pub trait MatcherEq: SealedInternal + Debug {
4649
fn matches(&self, o: &Self) -> bool;

rust/proxied.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ pub trait AsView: SealedInternal {
115115
fn as_view(&self) -> View<'_, Self::Proxied>;
116116
}
117117

118+
impl<T: Proxied> AsView for &T {
119+
type Proxied = T::Proxied;
120+
fn as_view(&self) -> View<'_, Self::Proxied> {
121+
(**self).as_view()
122+
}
123+
}
124+
125+
impl<T: Proxied> AsView for &mut T {
126+
type Proxied = T::Proxied;
127+
fn as_view(&self) -> View<'_, Self::Proxied> {
128+
(**self).as_view()
129+
}
130+
}
131+
118132
/// Used to turn another 'borrow' into a view proxy.
119133
///
120134
/// On a mut proxy this borrows to a View (semantically matching turning a `&mut
@@ -153,6 +167,24 @@ pub trait IntoView<'msg>: SealedInternal + AsView {
153167
'msg: 'shorter;
154168
}
155169

170+
impl<'msg, T: Proxied> IntoView<'msg> for &'msg T {
171+
fn into_view<'shorter>(self) -> View<'shorter, T>
172+
where
173+
'msg: 'shorter,
174+
{
175+
(*self).as_view()
176+
}
177+
}
178+
179+
impl<'msg, T: Proxied> IntoView<'msg> for &'msg mut T {
180+
fn into_view<'shorter>(self) -> View<'shorter, T>
181+
where
182+
'msg: 'shorter,
183+
{
184+
(*self).as_view()
185+
}
186+
}
187+
156188
/// Used to semantically do a cheap "to-mut-reference" conversion. This is
157189
/// implemented on both owned `Proxied` types as well as mut proxy types.
158190
///
@@ -164,6 +196,13 @@ pub trait AsMut: SealedInternal + AsView<Proxied = Self::MutProxied> {
164196
fn as_mut(&mut self) -> Mut<'_, Self::MutProxied>;
165197
}
166198

199+
impl<T: MutProxied> AsMut for &mut T {
200+
type MutProxied = T::MutProxied;
201+
fn as_mut(&mut self) -> Mut<'_, Self::MutProxied> {
202+
(*self).as_mut()
203+
}
204+
}
205+
167206
/// Used to turn another 'borrow' into a mut proxy.
168207
///
169208
/// On a mut proxy this will behave as a reborrow into a shorter lifetime
@@ -196,6 +235,15 @@ pub trait IntoMut<'msg>: SealedInternal + AsMut {
196235
'msg: 'shorter;
197236
}
198237

238+
impl<'msg, T: MutProxied> IntoMut<'msg> for &'msg mut T {
239+
fn into_mut<'shorter>(self) -> Mut<'shorter, T>
240+
where
241+
'msg: 'shorter,
242+
{
243+
(*self).as_mut()
244+
}
245+
}
246+
199247
/// A value to `Proxied`-value conversion that consumes the input value.
200248
///
201249
/// All setter functions accept types that implement `IntoProxied`. The purpose

rust/test/shared/message_generics_test.rs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use protos::*;
66
use googletest::prelude::*;
77
use protobuf::prelude::*;
88

9-
use protobuf::{AsMut, AsView, Message};
9+
use protobuf::{AsMut, AsView, IntoMut, IntoView, Message};
1010
use unittest_rust_proto::TestAllTypes;
1111

1212
fn f<M: Message, T: AsView<Proxied = M>>(msg_view: T) -> usize {
@@ -73,3 +73,76 @@ fn msg_used_generically_struct_test() {
7373
let empty: &[u8] = &[];
7474
expect_that!(proto_send_msg.encode(), eq(empty));
7575
}
76+
77+
#[gtest]
78+
fn as_view_serialize_test() {
79+
fn as_view_serialize<M: Message, T: AsView<Proxied = M>>(msg_view: T) -> usize {
80+
msg_view.as_view().serialize().unwrap().len()
81+
}
82+
let mut msg = TestAllTypes::new();
83+
expect_that!(as_view_serialize(msg.as_view()), eq(0));
84+
expect_that!(as_view_serialize(&msg), eq(0));
85+
expect_that!(as_view_serialize(&mut msg), eq(0));
86+
expect_that!(as_view_serialize(msg), eq(0));
87+
}
88+
89+
#[gtest]
90+
fn into_view_serialize_test() {
91+
fn into_view_serialize<'a, M: Message, T: IntoView<'a, Proxied = M>>(msg_view: T) -> usize {
92+
msg_view.into_view().serialize().unwrap().len()
93+
}
94+
let mut msg = TestAllTypes::new();
95+
expect_that!(into_view_serialize(msg.as_view()), eq(0));
96+
expect_that!(into_view_serialize(&msg), eq(0));
97+
expect_that!(into_view_serialize(&mut msg), eq(0));
98+
}
99+
100+
#[gtest]
101+
fn as_mut_clear_test() {
102+
fn as_mut_clear<M: Message, T: AsMut<MutProxied = M>>(mut msg_mut: T) {
103+
msg_mut.as_mut().clear();
104+
}
105+
106+
{
107+
let mut msg = TestAllTypes::new();
108+
msg.set_optional_int32(123);
109+
expect_that!(msg.has_optional_int32(), eq(true));
110+
as_mut_clear(msg.as_mut());
111+
expect_that!(msg.has_optional_int32(), eq(false));
112+
}
113+
{
114+
let mut msg = TestAllTypes::new();
115+
msg.set_optional_int32(123);
116+
expect_that!(msg.has_optional_int32(), eq(true));
117+
as_mut_clear(&mut msg);
118+
expect_that!(msg.has_optional_int32(), eq(false));
119+
}
120+
{
121+
let mut msg = TestAllTypes::new();
122+
msg.set_optional_int32(123);
123+
expect_that!(msg.has_optional_int32(), eq(true));
124+
as_mut_clear(msg); // msg itself is AsMut but this consumes the msg.
125+
}
126+
}
127+
128+
#[gtest]
129+
fn into_mut_clear_test() {
130+
fn into_mut_clear<'a, M: Message, T: IntoMut<'a, MutProxied = M>>(msg_mut: T) {
131+
msg_mut.into_mut().clear();
132+
}
133+
134+
{
135+
let mut msg = TestAllTypes::new();
136+
msg.set_optional_int32(123);
137+
expect_that!(msg.has_optional_int32(), eq(true));
138+
into_mut_clear(msg.as_mut());
139+
expect_that!(msg.has_optional_int32(), eq(false));
140+
}
141+
{
142+
let mut msg = TestAllTypes::new();
143+
msg.set_optional_int32(123);
144+
expect_that!(msg.has_optional_int32(), eq(true));
145+
into_mut_clear(&mut msg);
146+
expect_that!(msg.has_optional_int32(), eq(false));
147+
}
148+
}

0 commit comments

Comments
 (0)