#parser-generator #protocols #language #description #choose

protogen

协议描述语言与解析器生成器

1个不稳定版本

使用旧的Rust 2015

0.1.0 2018年12月17日

#21 in #choose


hci 中使用

MIT/Apache

73KB
2K SLoC

Protogen

Protogen是一种用于生成安全高效解析器和(最终)数据协议生成器的协议描述语言。

目前,该语言和(Rust)参考实现都处于非常初级的alpha版本,可能会发生重大变化。

有关在protogen中实现的较大规模协议的示例,请参阅 hci-rs

一个简单的.wav解析器看起来像这样

wave = {
  chunk_id: [u8; 4] | [b"RIFF"];
  @chunk_size: u32;
  public format: [u8; 4] | [b"WAVE"];
  @data_size: u32 = @chunk_size - 8;
  @data: [u8; @data_size];
  public chunks: apply @data many!(subchunk());
}

subchunk = {
  @id: [u8; 4];
  @size: u32;
  @data: [u8; @size];
  public subchunk: apply @data choose {
    FormatSubchunk = fmt_subchunk(@id) |
    DataSubchunk = data_subchunk(@id) |
    OtherSubchunk = other_subchunk(@id)
  };
}

fmt_subchunk ($id: [u8; 4] = b"fmt ") = {
  public audio_format: u16;
  public num_channels: u16;
  public sample_rate: u32;
  public byte_rate: u32;
  public block_align: u16;
  public bits_per_sample: u16;
}

data_subchunk ($id: [u8; 4] = b"data") = {
  public data: rest!();
}

other_subchunk (public $id: [u8; 4]) = {
  public data: rest!();
}

并且可以在Rust程序中使用

use wave::*;
use std::path::Path;
use std::fs::File;
use std::io::Read;
use std::str;
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let path = Path::new(args[1]);

    let mut file = File::open(&path).unwrap();
    let mut buf: Vec<u8> = vec![];
    file.read_to_end(&mut buf).unwrap();

    for chunk in parsed.get_chunks() {
        println!("Chunk: {:?}", chunk);
    }
}

依赖项

~1MB
~18K SLoC