scuffle_cedar_policy_codegen/
lib.rs1#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
30#![cfg_attr(docsrs, feature(doc_auto_cfg))]
31#![deny(missing_docs)]
32#![deny(unreachable_pub)]
33#![deny(clippy::mod_module_files)]
34#![deny(clippy::undocumented_unsafe_blocks)]
35#![deny(clippy::multiple_unsafe_ops_per_block)]
36
37mod cedar_action;
38mod cedar_namespace;
39mod codegen;
40mod error;
41mod module;
42mod types;
43mod utils;
44
45use cedar_policy_core::extensions::Extensions;
46use cedar_policy_core::validator::RawName;
47use cedar_policy_core::validator::cedar_schema::SchemaWarning;
48use cedar_policy_core::validator::json_schema::Fragment;
49pub use error::{CodegenError, CodegenResult};
50
51use crate::utils::process_fragment;
52
53pub struct Config {
55 pub(crate) crate_path: syn::Path,
56}
57
58impl Default for Config {
59 fn default() -> Self {
60 Self {
61 crate_path: syn::parse_quote!(::scuffle_cedar_policy),
62 }
63 }
64}
65
66pub struct CodegenOutput {
68 file: syn::File,
69 warnings: Vec<SchemaWarning>,
70}
71
72impl CodegenOutput {
73 pub fn warnings(&self) -> &[SchemaWarning] {
75 &self.warnings
76 }
77}
78
79impl quote::ToTokens for CodegenOutput {
80 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
81 self.file.to_tokens(tokens);
82 }
83}
84
85impl std::fmt::Display for CodegenOutput {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 prettyplease::unparse(&self.file).fmt(f)
88 }
89}
90
91impl Config {
92 pub fn new() -> Self {
94 Self::default()
95 }
96
97 pub fn crate_path(&mut self, path: syn::Path) -> &mut Self {
99 self.crate_path = path;
100 self
101 }
102
103 pub fn generate_from_schema(&self, schema: &str) -> CodegenResult<CodegenOutput> {
105 let (fragment, warnings) = Fragment::from_cedarschema_str(schema, Extensions::all_available())?;
106 self.generate_from_fragment(&fragment).map(|mut out| {
107 out.warnings.extend(warnings);
108 out
109 })
110 }
111
112 pub fn generate_from_json(&self, schema_json: &str) -> CodegenResult<CodegenOutput> {
114 let fragment = Fragment::from_json_str(schema_json)?;
115 self.generate_from_fragment(&fragment)
116 }
117
118 pub fn generate_from_fragment(&self, fragment: &Fragment<RawName>) -> CodegenResult<CodegenOutput> {
120 let file = process_fragment(fragment, self)?;
121
122 Ok(CodegenOutput {
123 file,
124 warnings: Vec::new(),
125 })
126 }
127}