Skip to content

Commit dcb55ff

Browse files
committed
reflect accessors v2
Accessor is now constructed from function pointers, and not codegenerated. Generated code size is about 10% less.
1 parent 482eb9d commit dcb55ff

File tree

6 files changed

+1247
-2469
lines changed

6 files changed

+1247
-2469
lines changed

src/lib/codegen.rs

Lines changed: 51 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ impl fmt::Show for RustType {
6161
}
6262

6363
impl RustType {
64+
fn is_primitive(&self) -> bool {
65+
match *self {
66+
RustType::Signed(..) |
67+
RustType::Unsigned(..) |
68+
RustType::Float(..) |
69+
RustType::Bool => true,
70+
_ => false,
71+
}
72+
}
73+
6474
fn is_ref(&self) -> bool {
6575
match *self {
6676
RustType::Ref(..) => true,
@@ -610,6 +620,34 @@ impl Field {
610620
self.proto_field.get_name(),
611621
self.proto_field.get_number())
612622
}
623+
624+
// name of function in protobuf::reflect::accessor
625+
// that generates accessor for this field
626+
fn make_accessor_fn(&self) -> String {
627+
let repeated_or_signular = match self.repeated {
628+
true => "repeated",
629+
false => "singular",
630+
};
631+
let suffix = match &self.type_name {
632+
t if t.is_primitive() => t.to_string(),
633+
&RustType::String => "string".to_string(),
634+
&RustType::Vec(box RustType::Unsigned(8)) => "bytes".to_string(),
635+
&RustType::Enum(..) => "enum".to_string(),
636+
&RustType::Message(..) => "message".to_string(),
637+
t => panic!("unexpected field type: {}", t),
638+
};
639+
format!("make_{}_{}_accessor", repeated_or_signular, suffix)
640+
}
641+
642+
// accessor function function params
643+
fn make_accessor_fn_fn_params(&self) -> Vec<&'static str> {
644+
let mut r = Vec::new();
645+
if !self.repeated {
646+
r.push("has");
647+
}
648+
r.push("get");
649+
r
650+
}
613651
}
614652

615653
#[deriving(Clone)]
@@ -1530,15 +1568,20 @@ fn write_message_descriptor_static(w: &mut IndentWriter) {
15301568
w.allow(&["unused_unsafe", "unused_mut"]);
15311569
w.def_fn(format!("descriptor_static(_: ::std::option::Option<{}>) -> &'static ::protobuf::reflect::MessageDescriptor", msg.type_name), |w| {
15321570
w.lazy_static_decl_get("descriptor", "::protobuf::reflect::MessageDescriptor", |w| {
1533-
let vec_type_param = format!(
1534-
"&'static ::protobuf::reflect::FieldAccessor<{}>",
1535-
msg.type_name);
1536-
w.write_line(format!("let mut fields: ::std::vec::Vec<{}> = ::std::vec::Vec::new();", vec_type_param));
1571+
w.write_line(format!("let mut fields = ::std::vec::Vec::new();"));
15371572
for field in msg.fields.iter() {
1538-
let acc_name = format!("{}_{}_acc", msg.type_name, field.name);
1539-
// TODO: transmute is because of https://github.com/mozilla/rust/issues/13887
1540-
w.write_line(format!("fields.push(unsafe {{ ::std::mem::transmute(&{} as &'static ::protobuf::reflect::FieldAccessor<{}>) }});",
1541-
acc_name, msg.type_name));
1573+
w.write_line(format!("fields.push(::protobuf::reflect::accessor::{}(", field.make_accessor_fn()));
1574+
w.indented(|w| {
1575+
w.write_line(format!("\"{}\",", field.name));
1576+
for f in field.make_accessor_fn_fn_params().iter() {
1577+
w.write_line(format!("{}::{}_{},",
1578+
msg.type_name,
1579+
f,
1580+
field.name,
1581+
));
1582+
}
1583+
});
1584+
w.write_line("));");
15421585
}
15431586
w.write_line(format!("::protobuf::reflect::MessageDescriptor::new::<{}>(", msg.type_name));
15441587
w.indented(|w| {
@@ -1596,116 +1639,6 @@ fn write_message_impl_show(w: &mut IndentWriter) {
15961639
});
15971640
}
15981641

1599-
fn write_message_descriptor_field(w: &mut IndentWriter) {
1600-
let msg = w.msg.unwrap();
1601-
let field = w.field.unwrap();
1602-
w.allow(&["non_camel_case_types"]);
1603-
let accessor_name = format!("{}_{}_acc", msg.type_name, field.name);
1604-
let accessor_type_name = accessor_name + "_type";
1605-
w.write_line(format!("struct {};", accessor_type_name));
1606-
w.write_line(format!("static {}: {} = {};", accessor_name, accessor_type_name, accessor_type_name));
1607-
w.write_line("");
1608-
w.impl_for_block(
1609-
format!("::protobuf::reflect::FieldAccessor<{}>", msg.type_name), accessor_type_name,
1610-
|w| {
1611-
w.def_fn("name(&self) -> &'static str", |w| {
1612-
w.write_line(format!("\"{}\"", field.name));
1613-
});
1614-
1615-
w.write_line("");
1616-
if field.repeated {
1617-
w.def_fn(format!("len_field(&self, m: &{}) -> uint", msg.type_name), |w| {
1618-
w.write_line(format!("m.get_{}().len()", field.name));
1619-
});
1620-
} else {
1621-
w.def_fn(format!("has_field(&self, m: &{}) -> bool", msg.type_name), |w| {
1622-
w.write_line(format!("m.has_{}()", field.name));
1623-
});
1624-
}
1625-
1626-
let name_suffix = match field.field_type {
1627-
FieldDescriptorProto_Type::TYPE_MESSAGE => "message".to_string(),
1628-
FieldDescriptorProto_Type::TYPE_ENUM => "enum".to_string(),
1629-
FieldDescriptorProto_Type::TYPE_STRING => "str".to_string(),
1630-
FieldDescriptorProto_Type::TYPE_BYTES => "bytes".to_string(),
1631-
_ => field.type_name.to_string(),
1632-
};
1633-
1634-
w.write_line("");
1635-
if field.repeated {
1636-
match field.field_type {
1637-
FieldDescriptorProto_Type::TYPE_MESSAGE => {
1638-
w.def_fn(format!("get_rep_message_item<'a>(&self, m: &'a {}, index: uint) -> &'a ::protobuf::Message",
1639-
msg.type_name),
1640-
|w| {
1641-
w.write_line(format!("&m.get_{}()[index] as &'a ::protobuf::Message", field.name));
1642-
});
1643-
},
1644-
FieldDescriptorProto_Type::TYPE_ENUM => {
1645-
w.def_fn(format!("get_rep_enum_item<'a>(&self, m: &{}, index: uint) -> &'static ::protobuf::reflect::EnumValueDescriptor",
1646-
msg.type_name),
1647-
|w| {
1648-
w.write_line(format!("m.get_{}()[index].descriptor()", field.name));
1649-
});
1650-
},
1651-
_ => {
1652-
w.def_fn(format!("get_rep_{}<'a>(&self, m: &'a {}) -> {}",
1653-
name_suffix,
1654-
msg.type_name,
1655-
w.field().get_xxx_return_type().ref_str("a")),
1656-
|w| {
1657-
w.write_line(format!("m.get_{}()", field.name));
1658-
});
1659-
},
1660-
};
1661-
} else {
1662-
let get_xxx_return_type = w.field().get_xxx_return_type();
1663-
let (lt_decl, lt_param) = match get_xxx_return_type.is_ref() {
1664-
true => ("<'a>", "'a "),
1665-
false => ("", ""),
1666-
};
1667-
let return_type_str = get_xxx_return_type.ref_str_safe("a");
1668-
match field.field_type {
1669-
FieldDescriptorProto_Type::TYPE_MESSAGE => {
1670-
w.def_fn(format!("get_message<'a>(&self, m: &'a {}) -> &'a ::protobuf::Message",
1671-
msg.type_name),
1672-
|w| {
1673-
w.write_line(format!("m.get_{}() as &'a ::protobuf::Message", field.name));
1674-
});
1675-
},
1676-
FieldDescriptorProto_Type::TYPE_ENUM => {
1677-
w.def_fn(format!("get_enum<'a>(&self, m: &{}) -> &'static ::protobuf::reflect::EnumValueDescriptor",
1678-
msg.type_name),
1679-
|w| {
1680-
w.write_line(format!("m.get_{}().descriptor()", field.name));
1681-
});
1682-
},
1683-
_ => {
1684-
w.def_fn(format!("get_{}{}(&self, m: &{}{}) -> {}",
1685-
name_suffix,
1686-
lt_decl,
1687-
lt_param,
1688-
msg.type_name,
1689-
return_type_str),
1690-
|w| {
1691-
w.write_line(format!("m.get_{}()", field.name));
1692-
});
1693-
},
1694-
};
1695-
}
1696-
});
1697-
}
1698-
1699-
fn write_message_descriptor(w: &mut IndentWriter) {
1700-
let msg = w.msg.unwrap();
1701-
for field in msg.fields.iter() {
1702-
w.bind_field(field, |w| {
1703-
w.write_line("");
1704-
write_message_descriptor_field(w);
1705-
});
1706-
}
1707-
}
1708-
17091642
fn write_message_impl_clear(w: &mut IndentWriter) {
17101643
let msg = w.msg.unwrap();
17111644
w.impl_for_block("::protobuf::Clear", msg.type_name.as_slice(), |w| {
@@ -1746,8 +1679,6 @@ fn write_message(m2: &MessageWithScope, root_scope: &RootScope, w: &mut IndentWr
17461679
if !msg.lite_runtime {
17471680
w.write_line("");
17481681
write_message_impl_show(w);
1749-
w.write_line("");
1750-
write_message_descriptor(w);
17511682
}
17521683

17531684
let mut nested_prefix = msg.type_name.to_string();

0 commit comments

Comments
 (0)