Bläddra i källkod

Add the ability to optionally list parameters for CMZ protocols

You can now write:

CMZProtocol! { proto_name<param1, param2>,
  [the rest is the same as before]
}

to say that param1 and param2 are public constants (Scalars) that will
be specified at runtime.  Then param1 and param2 can appear in the
statements in the statement list in the protocol declaration.

The "<param1, param2>" is optional, and defaults to specifying no
parameters.
Ian Goldberg 6 månader sedan
förälder
incheckning
cb0e99cd07
1 ändrade filer med 24 tillägg och 2 borttagningar
  1. 24 2
      cmzcred_derive/src/lib.rs

+ 24 - 2
cmzcred_derive/src/lib.rs

@@ -159,7 +159,7 @@ pub fn cmzcred_derive(input: TokenStream) -> TokenStream {
 
    The format is:
 
-   let proto = CMZProtocol! { proto_name,
+   let proto = CMZProtocol! { proto_name<param1,param2>,
      [ A: Cred {
          attr1: H,
          attr2: R,
@@ -175,12 +175,13 @@ pub fn cmzcred_derive(input: TokenStream) -> TokenStream {
        attr8: I,
        attr9: S,
      },
-     A.attr1 == B.attr3,
+     A.attr1 == B.attr3 + param1,
      A.attr1 == C.attr7,
    };
 
    The parameters are:
    - an identifier for the protocol
+   - an optional angle-bracketed list of parameters (identifiers)
    - a list of zero or more specifications for credentials that will be shown
    - a list of zero or more specifications for credentials that will be issued
    - zero or more statements relating the attributes in the credentials
@@ -328,6 +329,7 @@ impl<ShowOrIssue: Parse + Copy> Parse for CredSpecVec<ShowOrIssue> {
 #[derive(Debug)]
 struct ProtoSpec {
     proto_name: Ident,
+    params: Vec<Ident>,
     show_creds: Vec<CredSpec<ShowSpec>>,
     issue_creds: Vec<CredSpec<IssueSpec>>,
     statements: Vec<Expr>,
@@ -335,7 +337,26 @@ struct ProtoSpec {
 
 impl Parse for ProtoSpec {
     fn parse(input: ParseStream) -> Result<Self> {
+        let mut params: Vec<Ident> = Vec::new();
         let proto_name: Ident = input.parse()?;
+        // See if there are optional parameters; Rust does not provide a
+        // convenient angle-bracket parser like it does parens, square
+        // brackets, and braces, so we just roll our own.
+        if input.peek(Token![<]) {
+            input.parse::<Token![<]>()?;
+            loop {
+                if input.peek(Token![>]) {
+                    break;
+                }
+                let param: Ident = input.parse()?;
+                params.push(param);
+                if input.peek(Token![>]) {
+                    break;
+                }
+                input.parse::<Token![,]>()?;
+            }
+            input.parse::<Token![>]>()?;
+        }
         input.parse::<Token![,]>()?;
         let showvec: CredSpecVec<ShowSpec> = input.parse()?;
         input.parse::<Token![,]>()?;
@@ -347,6 +368,7 @@ impl Parse for ProtoSpec {
 
         Ok(ProtoSpec {
             proto_name,
+            params,
             show_creds: showvec.0,
             issue_creds: issuevec.0,
             statements,