1 // Copyright 2023 Google LLC
2 //
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 // https://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 use quote::quote;
16 use std::path::Path;
17
18 /// Generate the file preamble.
generate(path: &Path) -> proc_macro2::TokenStream19 pub fn generate(path: &Path) -> proc_macro2::TokenStream {
20 // TODO(mgeisler): Make the generated code free from warnings.
21 //
22 // The code either needs
23 //
24 // clippy_lints: "none",
25 // lints: "none",
26 //
27 // in the Android.bp file, or we need to add
28 //
29 // #![allow(warnings, missing_docs)]
30 //
31 // to the generated code. We cannot add the module-level attribute
32 // here because of how the generated code is used with include! in
33 // lmp/src/packets.rs.
34 let filename = path.file_name().unwrap().to_str().expect("non UTF-8 filename");
35 let module_doc_string = format!(" @generated rust packets from {filename}.");
36 // TODO(mgeisler): the doc comment below should be an outer
37 // comment (#![doc = ...]). However, people include the generated
38 // code in the middle of another module via include_str!:
39 //
40 // fn before() {}
41 // include_str!("generated.rs")
42 // fn after() {}
43 //
44 // It is illegal to have a //! comment in the middle of a file. We
45 // should refactor such usages to instead look like this:
46 //
47 // fn before() {}
48 // mod foo { include_str!("generated.rs") }
49 // use foo::*;
50 // fn after() {}
51 quote! {
52 #[doc = #module_doc_string]
53
54 use bytes::{Buf, BufMut, Bytes, BytesMut};
55 use std::convert::{TryFrom, TryInto};
56 use std::cell::Cell;
57 use std::fmt;
58 use std::result::Result;
59 use pdl_runtime::{DecodeError, EncodeError, Packet};
60
61 /// Private prevents users from creating arbitrary scalar values
62 /// in situations where the value needs to be validated.
63 /// Users can freely deref the value, but only the backend
64 /// may create it.
65 #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
66 pub struct Private<T>(T);
67
68 impl<T> std::ops::Deref for Private<T> {
69 type Target = T;
70 fn deref(&self) -> &Self::Target {
71 &self.0
72 }
73 }
74
75 impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 T::fmt(&self.0, f)
78 }
79 }
80 }
81 }
82
83 #[cfg(test)]
84 mod tests {
85 use super::*;
86 use crate::test_utils::{assert_snapshot_eq, format_rust};
87
88 #[test]
test_generate_preamble()89 fn test_generate_preamble() {
90 let actual_code = generate(Path::new("some/path/foo.pdl")).to_string();
91 assert_snapshot_eq("tests/generated/preamble.rs", &format_rust(&actual_code));
92 }
93 }
94