lua_protobuf_rs/descriptor/
message_descriptor.rs

1use 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}