use crate::output::primitive_data;
use crate::output::tree;
use crate::parse::context;
pub trait InputNode {
fn type_to_node() -> tree::Node;
fn data_to_node(&self) -> tree::Node;
fn oneof_variant(&self) -> Option<&'static str>;
fn parse_unknown(&self, context: &mut context::Context<'_>) -> bool;
}
pub trait ProtoMessage: InputNode {
fn proto_message_type() -> &'static str;
}
pub trait ProtoOneOf: InputNode {
fn proto_oneof_variant(&self) -> &'static str;
}
pub trait ProtoPrimitive: InputNode {
fn proto_primitive_type() -> &'static str;
fn proto_primitive_default() -> primitive_data::PrimitiveData;
fn proto_primitive_data(&self) -> primitive_data::PrimitiveData;
fn proto_primitive_is_default(&self) -> bool;
}
pub trait ProtoEnum: ProtoPrimitive {
fn proto_enum_type() -> &'static str;
fn proto_enum_default_variant() -> &'static str;
fn proto_enum_variant(&self) -> &'static str;
fn proto_enum_from_i32(x: i32) -> Option<Self>
where
Self: Sized;
}
impl<T: ProtoEnum> ProtoPrimitive for T {
fn proto_primitive_type() -> &'static str {
T::proto_enum_type()
}
fn proto_primitive_default() -> primitive_data::PrimitiveData {
primitive_data::PrimitiveData::Enum(T::proto_enum_default_variant())
}
fn proto_primitive_data(&self) -> primitive_data::PrimitiveData {
primitive_data::PrimitiveData::Enum(self.proto_enum_variant())
}
fn proto_primitive_is_default(&self) -> bool {
self.proto_enum_variant() == T::proto_enum_default_variant()
}
}
impl<T: ProtoPrimitive> InputNode for T {
fn type_to_node() -> tree::Node {
tree::NodeType::ProtoPrimitive(T::proto_primitive_type(), T::proto_primitive_default())
.into()
}
fn data_to_node(&self) -> tree::Node {
tree::NodeType::ProtoPrimitive(T::proto_primitive_type(), self.proto_primitive_data())
.into()
}
fn oneof_variant(&self) -> Option<&'static str> {
None
}
fn parse_unknown(&self, _context: &mut context::Context<'_>) -> bool {
false
}
}
impl InputNode for () {
fn type_to_node() -> tree::Node {
tree::NodeType::ProtoMessage("google.protobuf.Empty").into()
}
fn data_to_node(&self) -> tree::Node {
tree::NodeType::ProtoMessage("google.protobuf.Empty").into()
}
fn oneof_variant(&self) -> Option<&'static str> {
None
}
fn parse_unknown(&self, _context: &mut context::Context<'_>) -> bool {
false
}
}
impl ProtoMessage for () {
fn proto_message_type() -> &'static str {
"google.protobuf.Empty"
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::input::proto::substrait;
use crate::output::primitive_data;
use crate::output::tree;
#[test]
fn message() {
assert_eq!(substrait::Plan::proto_message_type(), "substrait.Plan");
assert_eq!(
substrait::Plan::type_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoMessage("substrait.Plan"),
data_type: None,
data: vec![],
}
);
let msg = substrait::Plan::default();
assert_eq!(
msg.data_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoMessage("substrait.Plan"),
data_type: None,
data: vec![],
}
);
assert_eq!(msg.oneof_variant(), None);
}
#[test]
fn oneof() {
assert_eq!(
substrait::plan_rel::RelType::type_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoMissingOneOf,
data_type: None,
data: vec![],
}
);
let oneof = substrait::plan_rel::RelType::Rel(substrait::Rel::default());
assert_eq!(oneof.proto_oneof_variant(), "rel");
assert_eq!(
oneof.data_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoMessage("substrait.Rel"),
data_type: None,
data: vec![],
}
);
assert_eq!(oneof.oneof_variant(), Some("rel"));
}
#[test]
fn enumeration() {
assert_eq!(
substrait::AggregationPhase::proto_enum_type(),
"substrait.AggregationPhase"
);
assert_eq!(
substrait::AggregationPhase::proto_enum_default_variant(),
"AGGREGATION_PHASE_UNSPECIFIED"
);
assert_eq!(
substrait::AggregationPhase::Unspecified.proto_enum_variant(),
"AGGREGATION_PHASE_UNSPECIFIED"
);
assert_eq!(
substrait::AggregationPhase::proto_primitive_type(),
"substrait.AggregationPhase"
);
assert_eq!(
substrait::AggregationPhase::proto_primitive_default(),
primitive_data::PrimitiveData::Enum("AGGREGATION_PHASE_UNSPECIFIED")
);
assert_eq!(
substrait::AggregationPhase::Unspecified.proto_primitive_data(),
primitive_data::PrimitiveData::Enum("AGGREGATION_PHASE_UNSPECIFIED")
);
assert_eq!(
substrait::AggregationPhase::type_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoPrimitive(
"substrait.AggregationPhase",
primitive_data::PrimitiveData::Enum("AGGREGATION_PHASE_UNSPECIFIED")
),
data_type: None,
data: vec![],
}
);
assert_eq!(
substrait::AggregationPhase::Unspecified.data_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoPrimitive(
"substrait.AggregationPhase",
primitive_data::PrimitiveData::Enum("AGGREGATION_PHASE_UNSPECIFIED")
),
data_type: None,
data: vec![],
}
);
assert_eq!(
substrait::AggregationPhase::Unspecified.oneof_variant(),
None
);
}
#[test]
fn primitive() {
assert_eq!(u32::proto_primitive_type(), "uint32");
assert_eq!(
u32::proto_primitive_default(),
primitive_data::PrimitiveData::Unsigned(0)
);
assert_eq!(
42u32.proto_primitive_data(),
primitive_data::PrimitiveData::Unsigned(42)
);
assert_eq!(
u32::type_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoPrimitive(
"uint32",
primitive_data::PrimitiveData::Unsigned(0)
),
data_type: None,
data: vec![],
}
);
assert_eq!(
42u32.data_to_node(),
tree::Node {
class: tree::Class::Misc,
brief: None,
summary: None,
node_type: tree::NodeType::ProtoPrimitive(
"uint32",
primitive_data::PrimitiveData::Unsigned(42)
),
data_type: None,
data: vec![],
}
);
assert_eq!(42u32.oneof_variant(), None);
}
}