Software APIs
ujson_rust.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_UJSON_UJSON_RUST_H_
6 #define OPENTITAN_SW_DEVICE_LIB_UJSON_UJSON_RUST_H_
7 
8 // Definitions of the UJSON macros that emit code that can be trivially
9 // transformed into rust code:
10 //
11 // Preprocess the input, grep out all the preprocessor noise,
12 // translate `rust_attr` into `#` (rust attributes) and finally format the code:
13 // gcc -nostdinc -I. -E -DRUST_PREPROCESSOR_EMIT <input_file> \
14 // | grep -v '#' \
15 // | sed -e "s/rust_attr/#/g" \
16 // | rustfmt > output_file
17 
18 #ifndef RUST_PREPROCESSOR_EMIT
19 #error "Do not include this file directly. Include ujson_derive.h instead."
20 #endif // RUST_PREPROCESSOR_EMIT
21 #include "sw/device/lib/base/adv_macros.h"
22 
23 #define uint64_t u64
24 #define uint32_t u32
25 #define uint16_t u16
26 #define uint8_t u8
27 #define size_t usize
28 
29 #define int64_t i64
30 #define int32_t i32
31 #define int16_t i16
32 #define int8_t i8
33 
34 #define RUST_DEFAULT_DERIVE \
35  Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq
36 
37 // clang-format off
38 rust_attr[allow(unused_imports)]
39 use opentitanlib::test_utils::status::status_t;
40 
41 // clang-format is turned off; as scary as these macros look, they look
42 // even scarier after clang-format is done with them.
43 #define ujson_struct_field_array_indirect() ujson_struct_field_array
44 #define ujson_struct_field_array(t_, sz_, ...) \
45  OT_IIF(OT_NOT(OT_VA_ARGS_COUNT(dummy, ##__VA_ARGS__))) \
46  ( /*then*/ \
47  arrayvec::ArrayVec<OT_EXPAND(t_, sz_)> \
48  , /*else*/ \
49  arrayvec::ArrayVec<OT_OBSTRUCT(ujson_struct_field_array_indirect)()(t_, __VA_ARGS__), sz_> \
50  ) /*endif*/
51 
52 #define ujson_struct_field(name_, type_, ...) \
53  pub OT_IIF(OT_NOT(OT_VA_ARGS_COUNT(dummy, ##__VA_ARGS__))) \
54  ( /*then*/ \
55  name_: type_ \
56  , /*else*/ \
57  name_: OT_EVAL(ujson_struct_field_array(type_, __VA_ARGS__)) \
58  ) /*endif*/,
59 
60 #define ujson_struct_string(name_, size_, ...) \
61  ujson_struct_field(name_, String, ##__VA_ARGS__)
62 
63 #define UJSON_DECLARE_STRUCT(formal_name_, name_, decl_, ...) \
64  OT_IIF(OT_NOT(OT_VA_ARGS_COUNT(dummy, ##__VA_ARGS__))) \
65  ( /*then*/ \
66  rust_attr[derive(RUST_DEFAULT_DERIVE)] /*transform into #[...] */ \
67  , /*else*/ \
68  rust_attr[derive(__VA_ARGS__)] /*transform into #[...] */ \
69  ) /*endif*/ \
70  rust_attr[allow(non_camel_case_types)] \
71  pub struct name_ { \
72  decl_(ujson_struct_field, ujson_struct_string) \
73  } \
74  rust_attr[allow(dead_code)] \
75  pub type formal_name_ = name_ /*eat_semicolon*/
76 
77 #define ujson_enum_value(formal_name_, name_, ...) \
78  pub OT_IIF(OT_NOT(OT_VA_ARGS_COUNT(dummy, ##__VA_ARGS__))) \
79  ( /*then*/ \
80  name_ \
81  , /*else*/ \
82  name_ = __VA_ARGS__ \
83  ) /*endif*/,
84 
85 #define UJSON_DECLARE_ENUM(formal_name_, name_, decl_, ...) \
86  OT_IIF(OT_NOT(OT_VA_ARGS_COUNT(dummy, ##__VA_ARGS__))) \
87  ( /*then*/ \
88  rust_attr[derive(RUST_DEFAULT_DERIVE)] /*transform into #[...] */ \
89  , /*else*/ \
90  rust_attr[derive(__VA_ARGS__)] /*transform into #[...] */ \
91  ) /*endif*/ \
92  rust_attr[repr(u32)] /* transform into #[...] */ \
93  rust_attr[allow(non_camel_case_types)] \
94  pub enum name_ { \
95  decl_(formal_name_, ujson_enum_value) \
96  RUST_ENUM_INTVALUE (u32), \
97  } \
98  rust_attr[allow(dead_code)] \
99  pub type formal_name_ = name_ /*eat_semicolon*/
100 // clang-format on
101 
102 //////////////////////////////////////////////////////////////////////
103 // Combined build-everything macro
104 //////////////////////////////////////////////////////////////////////
105 #define UJSON_SERDE_STRUCT(formal_name_, name_, decl_, ...) \
106  UJSON_DECLARE_STRUCT(formal_name_, name_, decl_, ##__VA_ARGS__)
107 
108 #define UJSON_SERDE_ENUM(formal_name_, name_, decl_, ...) \
109  UJSON_DECLARE_ENUM(formal_name_, name_, decl_, ##__VA_ARGS__)
110 
111 #define C_ONLY(x) const _ : () = {/* eat a semicolon */}
112 #define RUST_ONLY(x) x
113 #endif // OPENTITAN_SW_DEVICE_LIB_UJSON_UJSON_RUST_H_