@@ 30,7 30,7 @@ which will expand roughly the following:
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct User {
name: String,
- key: [u8; 128],
+ key: Vec<u8>,
id: u64,
}
```
@@ 1,3 1,102 @@
+/*!
+`bare_proc` provides a simple procedural macro that generates Rust types from BARE schema files.
+Generated types implicitly implement `serde::Serialize` and `serde::Deserialize`, as `serde_bare`
+is used to handle encoding and decoding. Please see
+[serde_bare's documentation](https://docs.rs/serde_bare/latest/serde_bare/) for information on how
+the Rust data model maps to the BARE data model.
+
+To use this macro, define a BARE schema file and populate it with type declarations.
+
+For example:
+
+
+```bare
+// schema.bare
+type PublicKey data[128]
+type Time str # ISO 8601
+
+type Department enum {
+ ACCOUNTING
+ ADMINISTRATION
+ CUSTOMER_SERVICE
+ DEVELOPMENT
+
+ # Reserved for the CEO
+ JSMITH = 99
+}
+
+type Address list<str>[4] # street, city, state, country
+
+type Customer struct {
+ name: str
+ email: str
+ address: Address
+ orders: list<struct {
+ orderId: i64
+ quantity: i32
+ }>
+ metadata: map<str><data>
+}
+
+type Employee struct {
+ name: str
+ email: str
+ address: Address
+ department: Department
+ hireDate: Time
+ publicKey: optional<PublicKey>
+ metadata: map<str><data>
+}
+
+type TerminatedEmployee void
+
+type Person union {Customer | Employee | TerminatedEmployee}
+```
+
+Then, within a Rust source file:
+
+```
+use bare_proc::bare_schema;
+
+bare_proc!("schema.bare");
+
+
+let noah = Employee {
+ name: "Noah",
+ email: "noah@packetlost.dev",
+ address: ["", "", "", ""],
+ department: Department::ACCOUNTING,
+ hireDate: Vec<u8>,
+ publicKey: None,
+ metadata: HashMap::new(),
+};
+
+```
+
+# BARE => Rust Data Mapping
+
+In most areas, the BARE data model maps cleanly to a Rust representation. Unless otherwise
+specified, the most obvious Rust data type is generated from a given BARE type. For example,
+a BARE `option<type>` is mapped to Rust's `Option<type>`, BARE unions and enums are mapped to
+Rust `enum`s. See below for opinions that this crate has around data types that do not map
+as cleanly or require additional explanation.
+
+## Maps
+
+BARE maps are interpreted as `HashMap<K, V>` in Rust. As of now, this is not configurable, but
+may be in the future.
+
+## Variable Length Integers
+
+The variable `uint` and `int` types are mapped to [`serde_bare::UInt`] and [`serde_bare::Int`]
+respectively. These types wrap `u64` and `i64` (the largest possible sized values stored in BARE
+variable length integers).
+
+Arrays that have 32 or less elements are mapped directly as Rust arrays, while BARE arrays with
+more than 32 elements are converted into `Vec<T>`.
+
+*/
+
mod parser;
use std::{collections::BTreeMap, fs::read_to_string};
@@ 13,9 112,15 @@ fn ident_from_string(s: &String) -> Ident {
Ident::new(s, Span::call_site())
}
+/// `bare_schema` parses a BARE schema file and generates equivalent Rust code that is capable of
+/// being serialized to and deserialized from bytes using the BARE encoding format. The macro takes
+/// exactly one argument, a string that will be parsed as path pointing to a BARE schema file. The
+/// path is treated as relative to the file location of the macro's use.
+/// For details on how the BARE data model maps to the Rust data model, see the [`Serialize`
+/// derive macro's documentation.](https://docs.rs/serde_bare/latest/serde_bare/)
+// TODO: add a link to that documentation
#[proc_macro]
pub fn bare_schema(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
- // TODO: support Into<PathBuf>
let input = parse_macro_input!(item as ExprLit);
let path = match input.lit {
syn::Lit::Str(s) => s,
@@ 32,6 137,7 @@ pub fn bare_schema(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
use std::io::{Error as IOError, Read, Write};
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
+ use serde_bare::{UInt, Int};
#(#user_type_syntax)*
}
@@ 312,11 418,13 @@ fn gen_anonymous(
fn gen_primative_type_def(p: &PrimativeType) -> TokenStream {
use PrimativeType::*;
match p {
- UInt | U64 => quote! { u64 },
+ UInt => quote! { UInt },
+ U64 => quote! { u64 },
U32 => quote! { u32 },
U16 => quote! { u16 },
U8 => quote! { u8 },
- Int | I64 => quote! { i64 },
+ Int => quote! { Int },
+ I64 => quote! { i64 },
I32 => quote! { i32 },
I16 => quote! { i16 },
I8 => quote! { i8 },