Skip to content

Instantly share code, notes, and snippets.

@Geal
Created March 27, 2019 12:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Geal/4418fdc7c938ecdfc9f27116f8869ad0 to your computer and use it in GitHub Desktop.
Save Geal/4418fdc7c938ecdfc9f27116f8869ad0 to your computer and use it in GitHub Desktop.
@0xa9970031d0caaf6d;
struct Biscuit {
authority @0 :Block;
blocks @1 :List(Block);
# each element must be 32 bytes
keys @2 :List(Data);
signature @3 :Signature;
}
struct Block {
index @0 :UInt32;
symbols @1 :List(Text);
facts @2 :List(Fact);
caveats @3 :List(Rule);
}
struct Fact {
predicate @0 :Predicate;
}
struct Rule {
head @0 :Predicate;
body @1 :List(Predicate);
constraints @2 :List(Constraint);
}
struct Predicate {
# symbol value
name @0 :UInt32;
ids @1 :List(ID);
}
struct Constraint {
id @0 :UInt32;
kind :union {
int @1 :IntConstraint;
str @2 :StringConstraint;
date @3 :DateConstraint;
symbol @4 :SymbolConstraint;
}
}
struct ID {
union {
symbol @0 :UInt32;
variable @1 :UInt32;
integer @2 :Int32;
str @3 :Text;
date @4 :UInt64;
}
}
struct IntConstraint {
union {
lower @0 :UInt64;
larger @1 :UInt64;
lowerOrEqual @2 :UInt64;
largeOrEqual @3 :UInt64;
equal @4 :UInt64;
# must be a set (no duplicates)
in @5 :List(UInt64);
# must be a set (no duplicates)
notIn @6 :List(UInt64);
}
}
struct StringConstraint {
union {
prefix @0 :Text;
suffix @1 :Text;
equal @2 :Text;
# must be a set (no duplicates)
in @3 :List(Text);
# must be a set (no duplicates)
notIn @4 :List(Text);
}
}
struct DateConstraint {
union {
before @0 :UInt64;
after @1 :UInt64;
}
}
struct SymbolConstraint {
union {
# must be a set (no duplicates)
in @0 :List(UInt64);
# must be a set (no duplicates)
notIn @1 :List(UInt64);
}
}
struct Signature {
# each element must be 32 bytes
gamma @0 :List(Data);
# each element must be 32 bytes
c @1 :List(Data);
#must be 32 bytes
w @2 :Data;
#must be 32 bytes
s @3 :Data;
}
use capnp::{message, serialize, serialize_packed, traits::{IntoInternalStructReader, IntoInternalListReader},
raw::get_struct_data_section};
use nom::HexDisplay;
mod generated;
use generated::{biscuit, block, constraint, fact, i_d, predicate, rule};
#[test]
fn serialize() {
let mut message = ::capnp::message::Builder::new_default();
let block_count = 2;
{
let mut biscuit = message.init_root::<biscuit::Builder>();
{
let mut authority = biscuit.reborrow().init_authority();
authority.set_index(0);
let mut symbols = authority.reborrow().init_symbols(4);
symbols.reborrow().set(0, "file1");
symbols.reborrow().set(1, "file2");
symbols.reborrow().set(2, "read");
symbols.reborrow().set(3, "write");
let mut facts = authority.reborrow().init_facts(3);
for fact_id in 0..3 {
let mut pred0 = facts.reborrow().get(fact_id).init_predicate();
pred0.set_name(0);
let mut ids = pred0.init_ids(3);
ids.reborrow().get(0).set_symbol(0);
ids.reborrow().get(1).set_symbol(1);
ids.reborrow().get(2).set_symbol(2);
}
}
{
let mut blocks = biscuit.reborrow().init_blocks(block_count);
for block_id in 0..block_count {
let mut block = blocks.reborrow().get(block_id);
block.set_index(1+block_id as u32);
let mut symbols = block.reborrow().init_symbols(1);
symbols.reborrow().set(0, "caveat1");
let mut caveats = block.reborrow().init_caveats(1);
let mut caveat = caveats.reborrow().get(0);
{
let mut head = caveat.reborrow().init_head();
let mut ids = head.init_ids(1);
ids.reborrow().get(0).set_variable(0);
}
let mut preds = caveat.reborrow().init_body(3);
{
let mut pred = preds.reborrow().get(0);
pred.set_name(0);
let mut ids = pred.init_ids(2);
ids.reborrow().get(0).set_symbol(0);
ids.reborrow().get(1).set_variable(1);
}
{
let mut pred = preds.reborrow().get(1);
pred.set_name(1);
let mut ids = pred.init_ids(2);
ids.reborrow().get(0).set_symbol(0);
ids.reborrow().get(1).set_symbol(1);
}
{
let mut pred = preds.reborrow().get(0);
pred.set_name(2);
let mut ids = pred.init_ids(3);
ids.reborrow().get(0).set_symbol(0);
ids.reborrow().get(1).set_variable(1);
ids.reborrow().get(2).set_symbol(2);
}
}
}
{
let mut keys = biscuit.reborrow().init_keys(block_count + 1);
for block_id in 0..block_count + 1 {
let key = [0u8; 32];
//keys.reborrow().get(block_id).set(&key[..]);
keys.reborrow().set(block_id, &key[..]);
}
}
{
let mut signature = biscuit.reborrow().init_signature();
let mut gamma = signature.reborrow().init_gamma(block_count + 1);
for block_id in 0..block_count + 1 {
let g = std::iter::repeat(b'a' + block_id as u8).take(32).collect::<Vec<_>>();
gamma.reborrow().set(block_id, &g[..]);
}
let mut c = signature.reborrow().init_c(block_count + 1);
for block_id in 0..block_count + 1 {
let scalar = std::iter::repeat(b'A' + block_id as u8).take(32).collect::<Vec<_>>();
c.reborrow().set(block_id, &scalar[..]);
}
let w = [b'='; 32];
signature.set_w(&w[..]);
let s = [b'!'; 32];
signature.set_s(&s[..]);
}
}
let mut v0: Vec<u8> = Vec::new();
//serialize_packed::write_message(&mut ::std::io::stdout(), &message)
serialize::write_message(&mut v0, &message).unwrap();
println!(
"basic serialized, {} blocks, {} bytes:\n{}",
block_count,
v0.len(),
(&v0[..]).to_hex(16)
);
let mut v1: Vec<u8> = Vec::new();
//serialize_packed::write_message(&mut ::std::io::stdout(), &message)
serialize_packed::write_message(&mut v1, &message).unwrap();
println!(
"packed serialized, {} blocks, {} bytes:\n{}",
block_count,
v1.len(),
(&v1[..]).to_hex(16)
);
let mut b = std::io::BufReader::new(&v1[..]);
let reader = serialize_packed::read_message(&mut b, ::capnp::message::ReaderOptions::new()).unwrap();
let token = reader.get_root::<biscuit::Reader>().unwrap();
{
let block = token.reborrow().get_authority().unwrap();
let r = block.reborrow().into_internal_struct_reader();
println!("index: {}", block.get_index());
println!("total_size: {:?}", r.total_size());
println!("data section size: {:?}", r.get_data_section_size());
println!("pointer section size: {:?}", r.get_pointer_section_size());
println!("data:\n{}", (r.get_data_section_as_blob()).to_hex(16));
//let canonicalized = block.canonicalize().unwrap();
//println!("canonicalized:\n{}", canonicalized.to_hex(16));
}
{
for block in token.reborrow().get_blocks().unwrap().iter() {
let r = block.reborrow().into_internal_struct_reader();
println!("index: {}", block.get_index());
println!("total_size: {:?}", r.total_size());
println!("data section size: {:?}", r.get_data_section_size());
println!("pointer section size: {:?}", r.get_pointer_section_size());
println!("pointer 0: {:?}", r.get_pointer_field(0).total_size());
println!("pointer 1: {:?}", r.get_pointer_field(1).total_size());
println!("pointer 2: {:?}", r.get_pointer_field(2).total_size());
println!("data:\n{}", (r.get_data_section_as_blob()).to_hex(16));
println!("data section:\n{}", get_struct_data_section(block.reborrow()).to_hex(16));
//let canonicalized = block.canonicalize().unwrap();
//println!("canonicalized:\n{}", canonicalized.to_hex(16));
}
}
{
let r = token.reborrow().get_blocks().unwrap().into_internal_list_reader();
println!("list reader len: {}", r.len());
for i in 0..r.len() {
let p = r.get_pointer_element(i);
println!("{}: size = {:?}", i, p.total_size().unwrap());
}
}
panic!();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment