lua_protobuf_rs/descriptor/
message_descriptor.rs1use anyhow::anyhow;
2use derive_more::{Deref, From, Into};
3use mlua::prelude::LuaUserData;
4use mlua::{AnyUserData, ErrorContext, MetaMethod, Table, UserDataMethods};
5use protobuf::reflect::MessageDescriptor;
6
7use crate::codec::LuaProtoCodec;
8use crate::descriptor::enum_descriptor::LuaEnumDescriptor;
9use crate::descriptor::field_descriptor::LuaFieldDescriptor;
10use crate::descriptor::file_descriptor::LuaFileDescriptor;
11use crate::descriptor::oneof_descriptor::LuaOneofDescriptor;
12use crate::descriptor_proto::descriptor_proto::LuaDescriptorProto;
13use crate::descriptor_proto::file_descriptor_proto::LuaFileDescriptorProto;
14use crate::message_dyn::LuaMessageDyn;
15
16#[derive(Clone, Eq, PartialEq, Hash, Deref, From, Into)]
17pub struct LuaMessageDescriptor(pub MessageDescriptor);
18
19impl LuaUserData for LuaMessageDescriptor {
20 fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
21 methods.add_method(MetaMethod::ToString, |_, this, ()| {
22 Ok(this.to_string())
23 });
24
25 methods.add_meta_method(MetaMethod::Eq, |_, this, other: AnyUserData| {
26 let other = other.borrow::<LuaMessageDescriptor>()?;
27 Ok(*this == *other)
28 });
29
30 methods.add_method("proto", |_, this, ()| {
31 let proto: LuaDescriptorProto = this.proto().clone().into();
32 Ok(proto)
33 });
34
35 methods.add_method("name", |_, this, ()| {
36 Ok(this.name().to_string())
37 });
38
39 methods.add_method("nested_messages", |_, this, ()| {
40 let nested_messages: Vec<LuaMessageDescriptor> = this.nested_messages().map(From::from).collect();
41 Ok(nested_messages)
42 });
43
44 methods.add_method("nested_enums", |_, this, ()| {
45 let nested_enums: Vec<LuaEnumDescriptor> = this.nested_enums().map(From::from).collect();
46 Ok(nested_enums)
47 });
48
49 methods.add_method("enclosing_message", |_, this, ()| {
50 let enclosing_message: Option<LuaMessageDescriptor> = this.enclosing_message().map(From::from);
51 Ok(enclosing_message)
52 });
53
54 methods.add_method("file_descriptor", |_, this, ()| {
55 let file_descriptor: LuaFileDescriptor = From::from(this.file_descriptor().clone());
56 Ok(file_descriptor)
57 });
58
59 methods.add_method("file_descriptor_proto", |_, this, ()| {
60 let proto: LuaFileDescriptorProto = this.file_descriptor_proto().clone().into();
61 Ok(proto)
62 });
63
64 methods.add_method("is_map_entry", |_, this, ()| {
65 Ok(this.is_map_entry())
66 });
67
68 methods.add_method("new_instance", |_, this, ()| {
69 Ok::<LuaMessageDyn, _>(this.new_instance().into())
70 });
71
72 methods.add_method("default_instance", |_, this, ()| {
73 match this.default_instance() {
74 None => {
75 Ok(None)
76 }
77 Some(instance) => {
78 Ok::<Option<LuaMessageDyn>, _>(Some(instance.clone_box().into()))
79 }
80 }
81 });
82
83 methods.add_method("clone_message", |_, this, ()| {
84 match this.enclosing_message() {
85 None => {
86 Ok(None)
87 }
88 Some(message) => {
89 Ok::<Option<LuaMessageDescriptor>, _>(Some(message.clone().into()))
90 }
91 }
92 });
93
94 methods.add_method("eq", |_, this, (a, b): (AnyUserData, AnyUserData)| {
95 let a = a.borrow::<LuaMessageDyn>()?;
96 let b = b.borrow::<LuaMessageDyn>()?;
97 Ok(MessageDescriptor::eq(this, &***a, &***b))
98 });
99
100 methods.add_method("full_name", |_, this, ()| {
101 Ok(this.full_name().to_string())
102 });
103
104 methods.add_method("name_to_package", |_, this, ()| {
105 Ok(this.name_to_package().to_string())
106 });
107
108 methods.add_method("all_oneofs", |_, this, ()| {
109 let all_oneofs: Vec<LuaOneofDescriptor> = this.all_oneofs().map(From::from).collect();
110 Ok(all_oneofs)
111 });
112
113 methods.add_method("oneofs", |_, this, ()| {
114 let oneofs: Vec<LuaOneofDescriptor> = this.oneofs().map(From::from).collect();
115 Ok(oneofs)
116 });
117
118 methods.add_method("oneof_by_name", |_, this, name: String| {
119 let descriptor: Option<LuaOneofDescriptor> = this.oneof_by_name(name.as_str()).map(From::from);
120 Ok(descriptor)
121 });
122
123 methods.add_method("fields", |_, this, ()| {
124 let fields: Vec<LuaFieldDescriptor> = this.fields().map(From::from).collect();
125 Ok(fields)
126 });
127
128 methods.add_method("extensions", |_, this, ()| {
129 let extensions: Vec<LuaFieldDescriptor> = this.extensions().map(From::from).collect();
130 Ok(extensions)
131 });
132
133 methods.add_method("field_by_name", |_, this, name: String| {
134 let field_descriptor: Option<LuaFieldDescriptor> = this.field_by_name(name.as_str()).map(From::from);
135 Ok(field_descriptor)
136 });
137
138 methods.add_method("field_by_name_or_json_name", |_, this, name: String| {
139 let field_descriptor: Option<LuaFieldDescriptor> = this.field_by_name_or_json_name(name.as_str()).map(From::from);
140 Ok(field_descriptor)
141 });
142
143 methods.add_method("field_by_number", |_, this, number: u32| {
144 let field_descriptor: Option<LuaFieldDescriptor> = this.field_by_number(number).map(From::from);
145 Ok(field_descriptor)
146 });
147
148 methods.add_method("parse_from_bytes", |lua, this, bytes_table: Table| {
149 let len = bytes_table.len()? as usize;
150 let mut bytes = Vec::with_capacity(len);
151 for byte in bytes_table.sequence_values::<u8>() {
152 bytes.push(byte.context("expect u8 in table, found other type")?);
153 }
154 let message = this.parse_from_bytes(bytes.as_slice()).map_err(|e| anyhow!(e))?;
155 let codec = LuaProtoCodec::default();
156 let message = codec.decode_message(lua, message.as_ref())?;
157 Ok(message)
158 });
159 }
160}