Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 54 additions & 8 deletions prost-reflect/src/descriptor/api.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::{
borrow::Cow,
collections::HashMap,
fmt, iter,
ops::{Range, RangeInclusive},
sync::Arc,
};

use prost::{
bytes::{Buf, BufMut},
bytes::{Buf, BufMut, Bytes},
encoding::{self, WireType},
DecodeError, EncodeError, Message,
};
Expand Down Expand Up @@ -108,6 +109,26 @@ impl Kind {
Kind::String | Kind::Bytes | Kind::Message(_) => WireType::LengthDelimited,
}
}

/// Returns the default value for the given protobuf type `kind`.
///
/// Unlike [`FieldDescriptor::default_value`], this method does not
/// look at field cardinality, so it will never return a list or map.
pub fn default_value(&self) -> Value {
match self {
Kind::Message(desc) => Value::Message(DynamicMessage::new(desc.clone())),
Kind::Enum(enum_ty) => Value::EnumNumber(enum_ty.default_value().number()),
Kind::Double => Value::F64(0.0),
Kind::Float => Value::F32(0.0),
Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => Value::I32(0),
Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => Value::I64(0),
Kind::Uint32 | Kind::Fixed32 => Value::U32(0),
Kind::Uint64 | Kind::Fixed64 => Value::U64(0),
Kind::Bool => Value::Bool(false),
Kind::String => Value::String(String::default()),
Kind::Bytes => Value::Bytes(Bytes::default()),
}
}
}

impl fmt::Debug for Kind {
Expand Down Expand Up @@ -1083,8 +1104,23 @@ impl FieldDescriptor {
})
}

pub(crate) fn default_value(&self) -> Option<&Value> {
self.inner().default.as_ref()
/// Returns the default value for this field.
///
/// This is equivalent to `kind().default_value()` except for the following cases:
///
/// * If the field is a map, an empty map is returned.
/// * If the field is `repeated`, an empty list is returned.
/// * If the field has a custom default value specified, that is returned (proto2 only).
pub fn default_value(&self) -> Value {
if self.is_list() {
Value::List(Vec::default())
} else if self.is_map() {
Value::Map(HashMap::default())
} else if let Some(default_value) = &self.inner().default {
default_value.clone()
} else {
self.kind().default_value()
}
}

pub(crate) fn is_packable(&self) -> bool {
Expand Down Expand Up @@ -1229,9 +1265,7 @@ impl ExtensionDescriptor {

/// Whether this field is a map type.
///
/// Equivalent to checking that the cardinality is `Repeated` and that
/// the field type is a message where [`is_map_entry`][MessageDescriptor::is_map_entry]
/// returns `true`.
/// Protobuf does not allow map fields to be extensions, so this will always return `false`.
pub fn is_map(&self) -> bool {
self.cardinality() == Cardinality::Repeated
&& match self.kind() {
Expand Down Expand Up @@ -1271,8 +1305,20 @@ impl ExtensionDescriptor {
}
}

pub(crate) fn default_value(&self) -> Option<&Value> {
self.inner().default.as_ref()
/// Returns the default value for this extension.
///
/// This is equivalent to `kind().default_value()`, unless the field is `repeated`,
/// in which case an empty list is returned.
pub fn default_value(&self) -> Value {
if self.is_list() {
Value::List(Vec::default())
} else if self.is_map() {
Value::Map(HashMap::default())
} else if let Some(default_value) = &self.inner().default {
default_value.clone()
} else {
self.kind().default_value()
}
}

pub(crate) fn is_packable(&self) -> bool {
Expand Down
47 changes: 7 additions & 40 deletions prost-reflect/src/dynamic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,56 +598,23 @@ impl ReflectMessage for DynamicMessage {
impl Value {
/// Returns the default value for the given protobuf field.
///
/// This is equivalent to [`default_value`][Value::default_value] except for the following cases:
///
/// * If the field is a map, an empty map is returned.
/// * If the field is `repeated`, an empty list is returned.
/// * If the field has a custom default value specified, that is returned (proto2 only).
/// See [FieldDescriptor::default_value] for more details.
pub fn default_value_for_field(field_desc: &FieldDescriptor) -> Self {
if field_desc.is_list() {
Value::List(Vec::default())
} else if field_desc.is_map() {
Value::Map(HashMap::default())
} else if let Some(default_value) = field_desc.default_value() {
default_value.clone()
} else {
Self::default_value(&field_desc.kind())
}
field_desc.default_value()
}

/// Returns the default value for the given protobuf extension field.
///
/// See [`default_value_for_field`][Value::default_value_for_field] for more details.
/// See [ExtensionDescriptor::default_value] for more details.
pub fn default_value_for_extension(extension_desc: &ExtensionDescriptor) -> Self {
if extension_desc.is_list() {
Value::List(Vec::default())
} else if extension_desc.is_map() {
Value::Map(HashMap::default())
} else if let Some(default_value) = extension_desc.default_value() {
default_value.clone()
} else {
Self::default_value(&extension_desc.kind())
}
extension_desc.default_value()
}

/// Returns the default value for the given protobuf type `kind`.
///
/// Unlike [`default_value_for_field`](Value::default_value_for_field), this method does not
/// look at field cardinality, so it will never return a list or map.
/// See [Kind::default_value] for more details.
pub fn default_value(kind: &Kind) -> Self {
match kind {
Kind::Message(desc) => Value::Message(DynamicMessage::new(desc.clone())),
Kind::Enum(enum_ty) => Value::EnumNumber(enum_ty.default_value().number()),
Kind::Double => Value::F64(0.0),
Kind::Float => Value::F32(0.0),
Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => Value::I32(0),
Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => Value::I64(0),
Kind::Uint32 | Kind::Fixed32 => Value::U32(0),
Kind::Uint64 | Kind::Fixed64 => Value::U64(0),
Kind::Bool => Value::Bool(false),
Kind::String => Value::String(String::default()),
Kind::Bytes => Value::Bytes(Bytes::default()),
}
kind.default_value()
}

/// Returns `true` if this is the default value for the given protobuf field.
Expand All @@ -662,7 +629,7 @@ impl Value {

/// Returns `true` if this is the default value for the given protobuf type `kind`.
pub fn is_default(&self, kind: &Kind) -> bool {
*self == Value::default_value(kind)
*self == kind.default_value()
}

/// Returns `true` if this value can be set for a given field.
Expand Down