blob: bc64817722d158ec64d21baae6a94b8af6babdd8 [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use quote::quote;
use std::path::Path;
/// Generate the file preamble.
pub fn generate(path: &Path) -> proc_macro2::TokenStream {
// TODO(mgeisler): Make the generated code free from warnings.
//
// The code either needs
//
// clippy_lints: "none",
// lints: "none",
//
// in the Android.bp file, or we need to add
//
// #![allow(warnings, missing_docs)]
//
// to the generated code. We cannot add the module-level attribute
// here because of how the generated code is used with include! in
// lmp/src/packets.rs.
let filename = path.file_name().unwrap().to_str().expect("non UTF-8 filename");
let module_doc_string = format!(" @generated rust packets from {filename}.");
// TODO(mgeisler): the doc comment below should be an outer
// comment (#![doc = ...]). However, people include the generated
// code in the middle of another module via include_str!:
//
// fn before() {}
// include_str!("generated.rs")
// fn after() {}
//
// It is illegal to have a //! comment in the middle of a file. We
// should refactor such usages to instead look like this:
//
// fn before() {}
// mod foo { include_str!("generated.rs") }
// use foo::*;
// fn after() {}
quote! {
#[doc = #module_doc_string]
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::convert::{TryFrom, TryInto};
use std::cell::Cell;
use std::fmt;
use std::result::Result;
use pdl_runtime::{DecodeError, EncodeError, Packet};
/// Private prevents users from creating arbitrary scalar values
/// in situations where the value needs to be validated.
/// Users can freely deref the value, but only the backend
/// may create it.
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Private<T>(T);
impl<T> std::ops::Deref for Private<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
T::fmt(&self.0, f)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{assert_snapshot_eq, format_rust};
#[test]
fn test_generate_preamble() {
let actual_code = generate(Path::new("some/path/foo.pdl")).to_string();
assert_snapshot_eq("tests/generated/preamble.rs", &format_rust(&actual_code));
}
}