use alloc::boxed::Box;
use core::fmt;
use core::ops::Deref;
pub unsafe trait DefaultInstance: Default + 'static {
fn default_instance() -> &'static Self;
}
pub struct MessageField<T: Default> {
inner: Option<Box<T>>,
}
impl<T: Default> MessageField<T> {
#[inline]
pub const fn none() -> Self {
Self { inner: None }
}
#[inline]
pub fn some(value: T) -> Self {
Self {
inner: Some(Box::new(value)),
}
}
#[inline]
pub fn from_box(value: Box<T>) -> Self {
Self { inner: Some(value) }
}
#[inline]
pub fn is_set(&self) -> bool {
self.inner.is_some()
}
#[inline]
pub fn is_unset(&self) -> bool {
self.inner.is_none()
}
#[inline]
pub fn as_option(&self) -> Option<&T> {
self.inner.as_deref()
}
#[inline]
pub fn as_option_mut(&mut self) -> Option<&mut T> {
self.inner.as_deref_mut()
}
#[inline]
pub fn take(&mut self) -> Option<T> {
self.inner.take().map(|b| *b)
}
#[inline]
pub fn get_or_insert_default(&mut self) -> &mut T {
self.inner.get_or_insert_default()
}
#[inline]
pub fn modify<F: FnOnce(&mut T)>(&mut self, f: F) {
f(self.get_or_insert_default());
}
#[inline]
pub fn into_option(self) -> Option<T> {
self.inner.map(|b| *b)
}
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
match self.inner {
Some(b) => Ok(*b),
None => Err(err),
}
}
#[inline]
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
match self.inner {
Some(b) => Ok(*b),
None => Err(err()),
}
}
}
impl<T: Default> Default for MessageField<T> {
#[inline]
fn default() -> Self {
Self::none()
}
}
impl<T: DefaultInstance> Deref for MessageField<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
match &self.inner {
Some(value) => value,
None => T::default_instance(),
}
}
}
impl<T: Default + Clone> Clone for MessageField<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T: DefaultInstance + PartialEq> PartialEq for MessageField<T> {
fn eq(&self, other: &Self) -> bool {
match (&self.inner, &other.inner) {
(Some(a), Some(b)) => a == b,
(None, None) => true,
(Some(a), None) => **a == *T::default_instance(),
(None, Some(b)) => *T::default_instance() == **b,
}
}
}
impl<T: DefaultInstance + Eq + PartialEq> Eq for MessageField<T> {}
impl<T: Default + fmt::Debug> fmt::Debug for MessageField<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
Some(value) => f.debug_tuple("MessageField::Set").field(value).finish(),
None => f.write_str("MessageField::Unset"),
}
}
}
impl<T: Default> From<Option<T>> for MessageField<T> {
fn from(opt: Option<T>) -> Self {
match opt {
Some(v) => Self::some(v),
None => Self::none(),
}
}
}
impl<T: Default> From<T> for MessageField<T> {
fn from(value: T) -> Self {
Self::some(value)
}
}
#[cfg(feature = "json")]
impl<T: Default + serde::Serialize> serde::Serialize for MessageField<T> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self.inner.as_deref() {
Some(v) => s.serialize_some(v),
None => s.serialize_none(),
}
}
}
#[cfg(feature = "json")]
impl<'de, T: Default + serde::Deserialize<'de>> serde::Deserialize<'de> for MessageField<T> {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
Option::<T>::deserialize(d).map(|opt| match opt {
Some(v) => Self::some(v),
None => Self::none(),
})
}
}
#[cfg(feature = "arbitrary")]
impl<'a, T: Default + arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for MessageField<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(if bool::arbitrary(u)? {
MessageField::some(T::arbitrary(u)?)
} else {
MessageField::none()
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Clone, Debug, Default, PartialEq)]
struct Inner {
value: i32,
name: alloc::string::String,
}
unsafe impl DefaultInstance for Inner {
fn default_instance() -> &'static Self {
static VALUE: crate::__private::OnceBox<Inner> = crate::__private::OnceBox::new();
VALUE.get_or_init(|| alloc::boxed::Box::new(Inner::default()))
}
}
#[test]
fn test_unset_derefs_to_default() {
let field: MessageField<Inner> = MessageField::none();
assert!(!field.is_set());
assert_eq!(field.value, 0);
assert_eq!(field.name, "");
}
#[test]
fn test_set_derefs_to_value() {
let field = MessageField::some(Inner {
value: 42,
name: "hello".into(),
});
assert!(field.is_set());
assert_eq!(field.value, 42);
assert_eq!(field.name, "hello");
}
#[test]
fn test_get_or_insert_default() {
let mut field: MessageField<Inner> = MessageField::none();
assert!(!field.is_set());
field.get_or_insert_default().value = 10;
assert!(field.is_set());
assert_eq!(field.value, 10);
}
#[test]
fn test_equality() {
let a: MessageField<Inner> = MessageField::none();
let b: MessageField<Inner> = MessageField::some(Inner::default());
assert_eq!(a, b);
}
#[test]
fn test_take() {
let mut field = MessageField::some(Inner {
value: 7,
name: "taken".into(),
});
let taken = field.take();
assert!(field.is_unset());
assert_eq!(taken.unwrap().value, 7);
}
#[test]
fn test_clone() {
let field = MessageField::some(Inner {
value: 99,
name: "clone".into(),
});
let cloned = field.clone();
assert_eq!(field, cloned);
}
#[test]
fn test_modify_initializes_unset_field() {
let mut field: MessageField<Inner> = MessageField::none();
field.modify(|inner| {
inner.value = 42;
inner.name = "hello".into();
});
assert!(field.is_set());
assert_eq!(field.value, 42);
assert_eq!(field.name, "hello");
}
#[test]
fn test_modify_updates_already_set_field() {
let mut field = MessageField::some(Inner {
value: 1,
name: "original".into(),
});
field.modify(|inner| {
inner.value = 99;
});
assert_eq!(field.value, 99);
assert_eq!(field.name, "original");
}
#[test]
fn test_modify_multiple_fields_in_one_call() {
let mut field: MessageField<Inner> = MessageField::none();
field.modify(|inner| {
inner.value = 10;
inner.name = "multi".into();
});
assert_eq!(field.value, 10);
assert_eq!(field.name, "multi");
}
#[test]
fn test_modify_noop_still_initializes_unset_field() {
let mut field: MessageField<Inner> = MessageField::none();
field.modify(|_| {});
assert!(field.is_set());
assert_eq!(field.value, 0);
assert_eq!(field.name, "");
}
#[test]
fn test_modify_closure_can_move_captured_values() {
let mut field: MessageField<Inner> = MessageField::none();
let name = alloc::string::String::from("moved");
field.modify(|inner| {
inner.name = name; });
assert_eq!(field.name, "moved");
}
#[cfg(feature = "json")]
mod serde_tests {
use super::*;
#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
struct Msg {
value: i32,
}
#[test]
fn unset_serializes_as_null() {
let f: MessageField<Msg> = MessageField::none();
assert_eq!(serde_json::to_string(&f).unwrap(), "null");
}
#[test]
fn set_serializes_as_inner_json() {
let f = MessageField::some(Msg { value: 42 });
let json = serde_json::to_string(&f).unwrap();
assert_eq!(json, r#"{"value":42}"#);
}
#[test]
fn null_deserializes_as_unset() {
let f: MessageField<Msg> = serde_json::from_str("null").unwrap();
assert!(f.is_unset());
}
#[test]
fn object_deserializes_as_set() {
let f: MessageField<Msg> = serde_json::from_str(r#"{"value":7}"#).unwrap();
assert!(f.is_set());
assert_eq!(f.as_option().unwrap().value, 7);
}
#[test]
fn round_trip_set_field() {
let original = MessageField::some(Msg { value: 99 });
let json = serde_json::to_string(&original).unwrap();
let recovered: MessageField<Msg> = serde_json::from_str(&json).unwrap();
assert_eq!(
original.as_option().unwrap().value,
recovered.as_option().unwrap().value
);
}
}
#[test]
fn test_into_option_unboxes() {
let field = MessageField::some(Inner {
value: 5,
name: "x".into(),
});
let opt: Option<Inner> = field.into_option();
assert_eq!(opt.unwrap().value, 5);
let field: MessageField<Inner> = MessageField::none();
assert!(field.into_option().is_none());
}
#[test]
fn test_ok_or() {
let set = MessageField::some(Inner {
value: 1,
name: "set".into(),
});
let r: Result<Inner, &str> = set.ok_or("missing");
assert_eq!(r.unwrap().value, 1);
let unset: MessageField<Inner> = MessageField::none();
assert_eq!(unset.ok_or("missing"), Err("missing"));
}
#[test]
fn test_ok_or_else() {
let set = MessageField::some(Inner {
value: 2,
name: "set".into(),
});
assert_eq!(set.ok_or_else(|| "unreachable").unwrap().value, 2);
let unset: MessageField<Inner> = MessageField::none();
assert_eq!(unset.ok_or_else(|| "missing"), Err("missing"));
}
#[test]
fn test_ok_or_else_closure_not_called_when_set() {
let set = MessageField::some(Inner::default());
let _ = set.ok_or_else(|| -> &str { panic!("closure must not run") });
}
#[test]
fn test_ok_or_else_partial_move() {
#[derive(Default)]
struct Request {
a: MessageField<Inner>,
b: MessageField<Inner>,
}
let req = Request {
a: MessageField::some(Inner {
value: 1,
..Default::default()
}),
b: MessageField::some(Inner {
value: 2,
..Default::default()
}),
};
let a = req.a.ok_or_else(|| "missing a").unwrap();
let b = req.b.ok_or_else(|| "missing b").unwrap();
assert_eq!(a.value, 1);
assert_eq!(b.value, 2);
}
#[test]
fn test_from_conversions() {
let field: MessageField<Inner> = Inner {
value: 1,
name: "from".into(),
}
.into();
assert!(field.is_set());
let field: MessageField<Inner> = None.into();
assert!(field.is_unset());
let field: MessageField<Inner> = Some(Inner {
value: 2,
name: "some".into(),
})
.into();
assert!(field.is_set());
}
}