• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "util/logger.h"
17 
18 #include "codegen/rust_code_emitter.h"
19 
20 #include "securec.h"
21 #include "util/file.h"
22 
23 namespace OHOS {
24 namespace Idl {
25 namespace {
26 const uint32_t WRAP_ANCHOR = 4;
27 }
28 
EmitInterface()29 void RustCodeEmitter::EmitInterface()
30 {
31     String filePath = String::Format("%s/%s.rs", directory_.string(), interfaceName_.string());
32     File file(filePath, File::WRITE);
33     StringBuilder sb;
34     EmitInterface(sb);
35     String data = sb.ToString();
36     file.WriteData(data.string(), data.GetLength());
37     file.Flush();
38     file.Close();
39 }
40 
EmitInterfaceProxy()41 void RustCodeEmitter::EmitInterfaceProxy()
42 {
43     return;
44 }
45 
EmitInterfaceStub()46 void RustCodeEmitter::EmitInterfaceStub()
47 {
48     return;
49 }
50 
EmitInterface(StringBuilder & sb)51 void RustCodeEmitter::EmitInterface(StringBuilder& sb)
52 {
53     if (metaInterface_->license_) {
54         EmitLicense(sb);
55         sb.Append("\n");
56     }
57     EmitMacros(sb);
58     EmitHeaders(sb);
59     sb.Append("\n");
60     EmitCommands(sb);
61     sb.Append("\n");
62     EmitRemoteObject(sb);
63     sb.Append("\n");
64     EmitBrokers(sb);
65     sb.Append("\n");
66     EmitRemoteRequest(sb);
67     sb.Append("\n");
68     EmitStub(sb);
69     sb.Append("\n");
70     EmitProxy(sb);
71 }
72 
EmitLicense(StringBuilder & sb)73 void RustCodeEmitter::EmitLicense(StringBuilder& sb)
74 {
75     sb.Append(metaInterface_->license_).Append("\n");
76 }
77 
EmitMacros(StringBuilder & sb)78 void RustCodeEmitter::EmitMacros(StringBuilder& sb)
79 {
80     sb.Append("#![allow(missing_docs)]\n");
81     sb.Append("#![allow(unused_variables)]\n");
82     sb.Append("#![allow(unused_mut)]\n");
83     sb.Append("\n");
84 }
EmitHeaders(StringBuilder & sb)85 void RustCodeEmitter::EmitHeaders(StringBuilder& sb)
86 {
87     EmitCommonHeaders(sb);
88     EmitIPCHeaders(sb);
89     if (EmitCustomHeaders(sb)) {
90         sb.Append("\n");
91     }
92 }
93 
EmitIPCHeaders(StringBuilder & sb)94 void RustCodeEmitter::EmitIPCHeaders(StringBuilder& sb)
95 {
96     sb.Append("extern crate ipc_rust;\n");
97     sb.Append("\n");
98     sb.Append("use ipc_rust::{\n");
99     sb.Append("    IRemoteBroker, IRemoteObj, RemoteStub, Result,\n");
100     sb.Append("    RemoteObj, define_remote_object, FIRST_CALL_TRANSACTION\n");
101     sb.Append("};\n");
102     sb.Append("use ipc_rust::{MsgParcel, BorrowedMsgParcel};\n");
103     sb.Append("\n");
104 }
105 
EmitCommonHeaders(StringBuilder & sb)106 void RustCodeEmitter::EmitCommonHeaders(StringBuilder& sb)
107 {
108     bool useMap = false;
109     for (int i = 0; i < metaComponent_->typeNumber_; i++) {
110         MetaType* mt = metaComponent_->types_[i];
111         switch (mt->kind_) {
112             case TypeKind::Map: {
113                 if (!useMap) {
114                     sb.Append("use std::collections::HashMap;\n");
115                     useMap = true;
116                 }
117                 break;
118             }
119 
120             default:
121                 break;
122         }
123     }
124     if (useMap) {
125         sb.Append("\n");
126     }
127 }
128 
TrimDot(const String & fpnp)129 String RustCodeEmitter::TrimDot(const String& fpnp)
130 {
131     if (fpnp.IsEmpty()) {
132         return nullptr;
133     }
134 
135     int left = 0;
136     int right = fpnp.GetLength() - 1;
137     while (fpnp[left] == ' ' || fpnp[left] == '.') {
138         left++;
139     }
140 
141     while (fpnp[right] == ' ' || fpnp[right] == '.') {
142         right--;
143     }
144 
145     if (left >= right) {
146         return nullptr;
147     }
148 
149     return fpnp.Substring(left, right + 1);
150 }
151 
GeneratePath(const String & fpnp)152 String RustCodeEmitter::GeneratePath(const String& fpnp)
153 {
154     int pos = fpnp.IndexOf("..");
155     if (pos == -1) {
156         String path = TrimDot(fpnp);
157         if (path.IsEmpty()) {
158             return nullptr;
159         }
160         return path.Replace(".", "::");
161     }
162 
163     String path = TrimDot(fpnp.Substring(0, pos + 1));
164     String file = TrimDot(fpnp.Substring(pos));
165     if (path.IsEmpty()) {
166         return nullptr;
167     }
168 
169     if (path.IndexOf("..") != -1 || file.IndexOf("..") != -1) {
170         return nullptr;
171     }
172 
173     StringBuilder realPath;
174     realPath.Append(path.Replace(".", "::")).Append("::{");
175     realPath.Append(file.Replace(".", ", "));
176     realPath.Append("}");
177 
178     return realPath.ToString();
179 }
180 
AppendRealPath(StringBuilder & sb,const String & fpnpp)181 bool RustCodeEmitter::AppendRealPath(StringBuilder& sb, const String& fpnpp)
182 {
183     String result = GeneratePath(fpnpp);
184     if (result.IsEmpty()) {
185         return false;
186     }
187     sb.Append("use ").Append(result).Append(";\n");
188     return true;
189 }
190 
EmitCustomHeaders(StringBuilder & sb)191 bool RustCodeEmitter::EmitCustomHeaders(StringBuilder& sb)
192 {
193     bool custom = false;
194     for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
195         MetaSequenceable* ms = metaComponent_->sequenceables_[i];
196         custom |= AppendRealPath(sb, String(ms->namespace_) + String(ms->name_));
197     }
198 
199     for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
200         MetaInterface* mi = metaComponent_->interfaces_[i];
201         if (mi->external_) {
202             custom |= AppendRealPath(sb, String(mi->namespace_) + String(mi->name_));
203         }
204     }
205     return custom;
206 }
207 
EmitCommands(StringBuilder & sb)208 void RustCodeEmitter::EmitCommands(StringBuilder& sb)
209 {
210     EmitCommandEnums(sb);
211 }
212 
AppendCommandEnums(StringBuilder & sb)213 void RustCodeEmitter::AppendCommandEnums(StringBuilder& sb)
214 {
215     if (metaInterface_->methodNumber_ > 0) {
216         sb.AppendFormat("    %s  = FIRST_CALL_TRANSACTION,\n",
217             GetCodeFromMethod(metaInterface_->methods_[0]->name_).string());
218     }
219 
220     for (int i = 1; i < metaInterface_->methodNumber_; i++) {
221         MetaMethod* mm = metaInterface_->methods_[i];
222         sb.AppendFormat("    %s,\n", GetCodeFromMethod(mm->name_).string(), i);
223     }
224 }
225 
GetCodeFromMethod(const char * name)226 String RustCodeEmitter::GetCodeFromMethod(const char* name)
227 {
228     StringBuilder sb;
229     sb.Append("Code");
230     const char* p = name;
231     bool hasUpper = false;
232     while (p != nullptr && *p != '\0') {
233         if (*p != '_') {
234             if (!hasUpper) {
235                 sb.Append(toupper(*p));
236                 hasUpper = true;
237             } else {
238                 sb.Append(*p);
239             }
240         } else {
241             hasUpper = false;
242         }
243         p++;
244     }
245     return sb.ToString();
246 }
247 
GetNameFromParameter(const char * name)248 String RustCodeEmitter::GetNameFromParameter(const char* name)
249 {
250     StringBuilder sb;
251     const char* p = name;
252     bool start = true;
253     while (p != nullptr && *p != '\0') {
254         if (start) {
255             if (isupper(*p)) {
256                 sb.Append('p');
257             }
258             start = false;
259         }
260 
261         if (isupper(*p)) {
262             sb.Append('_');
263             sb.Append(tolower(*p));
264         } else {
265             sb.Append(*p);
266         }
267         p++;
268     }
269     return sb.ToString();
270 }
271 
EmitCommandEnums(StringBuilder & sb)272 void RustCodeEmitter::EmitCommandEnums(StringBuilder& sb)
273 {
274     sb.AppendFormat("pub enum %sCode {\n", interfaceName_.string());
275     AppendCommandEnums(sb);
276     sb.Append("}\n");
277 }
278 
EmitRemoteObject(StringBuilder & sb)279 void RustCodeEmitter::EmitRemoteObject(StringBuilder& sb)
280 {
281     sb.Append("define_remote_object!(\n");
282     if (interfaceFullName_.StartsWith(".")) {
283         sb.AppendFormat("    %s[\"%s\"] {\n", interfaceName_.string(), interfaceName_.string());
284     } else {
285         sb.AppendFormat("    %s[\"%s\"] {\n", interfaceName_.string(), interfaceFullName_.string());
286     }
287     sb.AppendFormat("        stub: %s(on_remote_request),\n", stubName_.string());
288     sb.AppendFormat("        proxy: %s,\n", proxyName_.string());
289     sb.Append("    }\n");
290     sb.Append(");\n");
291 }
292 
EmitBrokers(StringBuilder & sb)293 void RustCodeEmitter::EmitBrokers(StringBuilder& sb)
294 {
295     sb.AppendFormat("pub trait %s: IRemoteBroker {\n", interfaceName_.string());
296     AppendBrokerMethods(sb);
297     sb.Append("}\n");
298 }
299 
WrapLine(StringBuilder & sb,int index,const String & prefix)300 void RustCodeEmitter::WrapLine(StringBuilder& sb, int index, const String& prefix)
301 {
302     if ((index + 1) % WRAP_ANCHOR == 0) {
303         sb.AppendFormat(",\n%s", prefix.string());
304     } else {
305         sb.Append(", ");
306     }
307 }
308 
AppendBrokerMethods(StringBuilder & sb)309 void RustCodeEmitter::AppendBrokerMethods(StringBuilder& sb)
310 {
311     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
312         MetaMethod* mm = metaInterface_->methods_[i];
313         sb.AppendFormat("    fn %s(&self", mm->name_);
314         for (int i = 0; i < mm->parameterNumber_; i++) {
315             WrapLine(sb, i, "        ");
316             AppendBrokerParameters(sb, mm->parameters_[i]);
317         }
318         sb.AppendFormat(") -> Result<%s>;\n", ConvertType(metaComponent_->types_[mm->returnTypeIndex_]).string());
319     }
320 }
321 
AppendBrokerParameters(StringBuilder & sb,MetaParameter * mp)322 void RustCodeEmitter::AppendBrokerParameters(StringBuilder& sb, MetaParameter* mp)
323 {
324     sb.AppendFormat("%s: &%s",
325         GetNameFromParameter(mp->name_).string(), ConvertType(metaComponent_->types_[mp->typeIndex_], true).string());
326 }
327 
ConvertType(MetaType * mt,bool pt)328 String RustCodeEmitter::ConvertType(MetaType* mt, bool pt)
329 {
330     switch (mt->kind_) {
331         case TypeKind::Unknown:
332         case TypeKind::Void:
333             return "()";
334         case TypeKind::Char:
335             return "char";
336         case TypeKind::Boolean:
337             return "bool";
338         case TypeKind::Byte:
339             return "i8";
340         case TypeKind::Short:
341             return "i16";
342         case TypeKind::Integer:
343             return "i32";
344         case TypeKind::Long:
345             return "i64";
346         case TypeKind::Float:
347             return "f32";
348         case TypeKind::Double:
349             return "f64";
350         case TypeKind::String:
351             return pt ? "str" : "String";
352         case TypeKind::Sequenceable:
353             return  metaComponent_->sequenceables_[mt->index_]->name_;
354         case TypeKind::Interface:
355             return metaComponent_->interfaces_[mt->index_]->name_;
356         case TypeKind::Map:
357             return String::Format("HashMap<%s, %s>",
358                 ConvertType(metaComponent_->types_[mt->nestedTypeIndexes_[0]]).string(),
359                 ConvertType(metaComponent_->types_[mt->nestedTypeIndexes_[1]]).string());
360         case TypeKind::List:
361         case TypeKind::Array:
362             return  String::Format((pt ? "[%s]" : "Vec<%s>"),
363                 ConvertType(metaComponent_->types_[mt->nestedTypeIndexes_[0]]).string());
364         default:
365             return "()";
366     }
367 }
368 
EmitRemoteRequest(StringBuilder & sb)369 void RustCodeEmitter::EmitRemoteRequest(StringBuilder& sb)
370 {
371     sb.AppendFormat("fn on_remote_request(stub: &dyn %s, code: u32, data: &BorrowedMsgParcel,\n",
372         interfaceName_.string());
373     sb.Append("    reply: &mut BorrowedMsgParcel) -> Result<()> {\n");
374     sb.Append("    match code {\n");
375     AddRemoteRequestMethods(sb);
376     sb.Append("        _ => Err(-1)\n");
377     sb.Append("    }\n");
378     sb.Append("}\n");
379 }
380 
AddRemoteRequestParameters(StringBuilder & sb,MetaMethod * mm)381 void RustCodeEmitter::AddRemoteRequestParameters(StringBuilder& sb, MetaMethod* mm)
382 {
383     for (int i = 0; i < mm->parameterNumber_; i++) {
384         MetaParameter* mp = mm->parameters_[i];
385         sb.AppendFormat("&%s", GetNameFromParameter(mp->name_).string());
386         if (i + 1 != mm->parameterNumber_) {
387             WrapLine(sb, i, "                ");
388         }
389     }
390 }
391 
ReadListFromParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)392 void RustCodeEmitter::ReadListFromParcel(StringBuilder& sb, MetaType* mt, const String& result,
393     const String& name, const String& prefix)
394 {
395     sb.Append(prefix).AppendFormat("let %s : %s = %s.read()?;\n",
396         name.string(), ConvertType(mt).string(), result.string());
397 }
398 
ReadMapFromParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)399 void RustCodeEmitter::ReadMapFromParcel(StringBuilder& sb, MetaType* mt, const String& result,
400     const String& name, const String& prefix)
401 {
402     sb.Append(prefix).AppendFormat("let mut %s = HashMap::new();\n", name.string());
403     sb.Append(prefix).AppendFormat("let len = %s.read()?;\n", result.string());
404     sb.Append(prefix).Append("for i in 0..len {\n");
405     StringBuilder k;
406     StringBuilder v;
407     k.Append(name).Append("k");
408     v.Append(name).Append("v");
409     ReadFromParcel(sb, metaComponent_->types_[mt->nestedTypeIndexes_[0]],
410         result, k.ToString().string(), prefix + "    ");
411     ReadFromParcel(sb, metaComponent_->types_[mt->nestedTypeIndexes_[1]],
412         result, v.ToString().string(), prefix + "    ");
413     sb.Append(prefix + "    ").AppendFormat("%s.insert(%s, %s);\n",
414         name.string(), k.ToString().string(), v.ToString().string());
415     sb.Append(prefix).Append("}\n");
416 }
417 
ReadFromParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)418 void RustCodeEmitter::ReadFromParcel(StringBuilder& sb, MetaType* mt, const String& result,
419     const String& name, const String& prefix)
420 {
421     if (mt->kind_ == TypeKind::Map) {
422         ReadMapFromParcel(sb, mt, result, name, prefix);
423     } else if (mt->kind_ == TypeKind::List || mt->kind_ == TypeKind::Array) {
424         ReadListFromParcel(sb, mt, result, name, prefix);
425     } else {
426         sb.Append(prefix).AppendFormat("let %s : %s = %s.read()?;\n",
427             name.string(), ConvertType(mt).string(), result.string());
428     }
429 }
430 
WriteListToParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)431 void RustCodeEmitter::WriteListToParcel(StringBuilder& sb, MetaType* mt, const String& result,
432     const String& name, const String& prefix)
433 {
434     sb.Append(prefix).AppendFormat("%s.write(&%s)?;\n", result.string(), name.string());
435 }
436 
WriteMapToParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)437 void RustCodeEmitter::WriteMapToParcel(StringBuilder& sb, MetaType* mt, const String& result,
438     const String& name, const String& prefix)
439 {
440     sb.Append(prefix).AppendFormat("%s.write(&(%s.len() as u32))?;\n", result.string(), name.string());
441     sb.Append(prefix).AppendFormat("for (key, value) in %s.iter() {\n", name.string());
442     WriteToParcel(sb, metaComponent_->types_[mt->nestedTypeIndexes_[0]], result, "key", prefix + "    ");
443     WriteToParcel(sb, metaComponent_->types_[mt->nestedTypeIndexes_[1]], result, "value", prefix + "    ");
444     sb.Append(prefix).Append("}\n");
445 }
446 
WriteToParcel(StringBuilder & sb,MetaType * mt,const String & result,const String & name,const String & prefix)447 void RustCodeEmitter::WriteToParcel(StringBuilder& sb, MetaType* mt, const String& result,
448     const String& name, const String& prefix)
449 {
450     if (mt->kind_ == TypeKind::Map) {
451         WriteMapToParcel(sb, mt, result, name, prefix);
452     } else if (mt->kind_ == TypeKind::List || mt->kind_ == TypeKind::Array) {
453         WriteListToParcel(sb, mt, result, name, prefix);
454     } else {
455         sb.Append(prefix).AppendFormat("%s.write(&%s)?;\n", result.string(), name.string());
456     }
457 }
458 
AddRemoteRequestMethods(StringBuilder & sb)459 void RustCodeEmitter::AddRemoteRequestMethods(StringBuilder& sb)
460 {
461     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
462         MetaMethod* mm = metaInterface_->methods_[i];
463         sb.AppendFormat("        %d => {\n", i + 1);
464         for (int j = 0; j < mm->parameterNumber_; j++) {
465             ReadFromParcel(sb, metaComponent_->types_[mm->parameters_[j]->typeIndex_], "data",
466                 GetNameFromParameter(mm->parameters_[j]->name_), "            ");
467         }
468         MetaType* mt = metaComponent_->types_[mm->returnTypeIndex_];
469         if (mt->kind_ != TypeKind::Unknown && mt->kind_ != TypeKind::Void) {
470             sb.AppendFormat("            let result = stub.%s(", mm->name_);
471         } else {
472             sb.AppendFormat("            stub.%s(", mm->name_);
473         }
474         AddRemoteRequestParameters(sb, mm);
475         sb.Append(")?;\n");
476         if (mt->kind_ != TypeKind::Unknown && mt->kind_ != TypeKind::Void) {
477             WriteToParcel(sb, mt, "reply", "result", "            ");
478         }
479         sb.Append("            Ok(())\n");
480         sb.Append("        }\n");
481     }
482 }
483 
EmitStub(StringBuilder & sb)484 void RustCodeEmitter::EmitStub(StringBuilder& sb)
485 {
486     sb.AppendFormat("impl %s for RemoteStub<%s> {\n", interfaceName_.string(), stubName_.string());
487     AppendStubMethods(sb);
488     sb.Append("}\n");
489 }
490 
AppendStubParameters(StringBuilder & sb,MetaMethod * mm)491 void RustCodeEmitter::AppendStubParameters(StringBuilder& sb, MetaMethod* mm)
492 {
493     for (int i = 0; i < mm->parameterNumber_; i++) {
494         sb.Append(GetNameFromParameter(mm->parameters_[i]->name_));
495         if (i + 1 != mm->parameterNumber_) {
496             WrapLine(sb, i, "                ");
497         }
498     }
499 }
500 
AppendStubMethods(StringBuilder & sb)501 void RustCodeEmitter::AppendStubMethods(StringBuilder& sb)
502 {
503     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
504         MetaMethod* mm = metaInterface_->methods_[i];
505         sb.AppendFormat("    fn %s(&self", mm->name_);
506         for (int i = 0; i < mm->parameterNumber_; i++) {
507             WrapLine(sb, i, "        ");
508             AppendBrokerParameters(sb, mm->parameters_[i]);
509         }
510 
511         sb.AppendFormat(") -> Result<%s> {\n",
512             ConvertType(metaComponent_->types_[mm->returnTypeIndex_]).string());
513         sb.AppendFormat("        self.0.%s(", mm->name_);
514         AppendStubParameters(sb, mm);
515         sb.Append(")\n");
516         sb.Append("    }\n");
517         if (i != metaInterface_->methodNumber_ - 1) {
518             sb.Append("\n");
519         }
520     }
521 }
522 
EmitProxy(StringBuilder & sb)523 void RustCodeEmitter::EmitProxy(StringBuilder& sb)
524 {
525     sb.AppendFormat("impl %s for %s {\n", interfaceName_.string(), proxyName_.string());
526     AppendProxyMethods(sb);
527     sb.Append("}\n");
528 }
529 
AppendProxyMethods(StringBuilder & sb)530 void RustCodeEmitter::AppendProxyMethods(StringBuilder& sb)
531 {
532     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
533         MetaMethod* mm = metaInterface_->methods_[i];
534         sb.AppendFormat("    fn %s(&self", mm->name_);
535         for (int i = 0; i < mm->parameterNumber_; i++) {
536             WrapLine(sb, i, "        ");
537             AppendBrokerParameters(sb, mm->parameters_[i]);
538         }
539         sb.AppendFormat(") -> Result<%s> {\n",
540             ConvertType(metaComponent_->types_[mm->returnTypeIndex_]).string());
541         sb.Append("        let mut data = MsgParcel::new().expect(\"MsgParcel should success\");\n");
542         for (int j = 0; j < mm->parameterNumber_; j++) {
543             WriteToParcel(sb, metaComponent_->types_[mm->parameters_[j]->typeIndex_], "data",
544                 GetNameFromParameter(mm->parameters_[j]->name_), "        ");
545         }
546         MetaType* mt = metaComponent_->types_[mm->returnTypeIndex_];
547         if (mt->kind_ == TypeKind::Unknown || mt->kind_ == TypeKind::Void) {
548             sb.AppendFormat("        let _reply = self.remote.send_request(%sCode", interfaceName_.string());
549         } else {
550             sb.AppendFormat("        let reply = self.remote.send_request(%sCode", interfaceName_.string());
551         }
552         sb.AppendFormat("::%s as u32, &data, ", GetCodeFromMethod(mm->name_).string());
553         if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0) {
554             sb.Append("true");
555         } else {
556             sb.Append("false");
557         }
558         sb.Append(")?;\n");
559         if (mt->kind_ == TypeKind::Unknown || mt->kind_ == TypeKind::Void) {
560             sb.Append("        ").Append("Ok(())\n");
561         } else {
562             ReadFromParcel(sb, mt, "reply", "result", "        ");
563             sb.Append("        ").Append("Ok(result)\n");
564         }
565         sb.Append("    }\n");
566 
567         if (i != metaInterface_->methodNumber_ - 1) {
568             sb.Append("\n");
569         }
570     }
571 }
572 }
573 }
574