use crate::pack_parse::*;
#[derive(Clone, Copy)]
pub enum PackStructAttributeKind {
SizeBytes,
DefaultIntEndianness,
BitNumbering
}
impl PackStructAttributeKind {
fn get_attr_name(&self) -> &'static str {
use self::PackStructAttributeKind::*;
match *self {
SizeBytes => "size_bytes",
DefaultIntEndianness => "endian",
BitNumbering => "bit_numbering"
}
}
}
pub enum PackStructAttribute {
SizeBytes(usize),
DefaultIntEndianness(IntegerEndianness),
BitNumbering(BitNumbering)
}
impl PackStructAttribute {
pub fn parse(name: &str, val: &str) -> Result<Self, String> {
if name == PackStructAttributeKind::DefaultIntEndianness.get_attr_name() {
let v = IntegerEndianness::from_str(val).ok_or_else(|| format!("Invalid default int endian value: {}", val))?;
return Ok(PackStructAttribute::DefaultIntEndianness(v));
}
if name == PackStructAttributeKind::BitNumbering.get_attr_name() {
let b = BitNumbering::from_str(val).expect("Invalid bit numbering attribute value");
return Ok(PackStructAttribute::BitNumbering(b));
}
if name == PackStructAttributeKind::SizeBytes.get_attr_name() {
let b = parse_num(val)?;
return Ok(PackStructAttribute::SizeBytes(b));
}
Err(format!("Unknown struct attribute: {}, value {}", name, val))
}
pub fn parse_all(attributes: &[(String, String)]) -> Vec<Self> {
let mut r = vec![];
for &(ref name, ref val) in attributes {
if let Ok(attr) = Self::parse(name, val) {
r.push(attr)
}
}
r
}
}
#[derive(Clone, Copy)]
pub enum PackFieldAttributeKind {
IntEndiannes,
BitPosition,
BytePosition,
ElementSizeBytes,
ElementSizeBits,
SizeBytes,
SizeBits,
Ty
}
impl PackFieldAttributeKind {
fn get_attr_name(&self) -> &'static str {
use self::PackFieldAttributeKind::*;
match *self {
IntEndiannes => "endian",
BitPosition => "bits",
BytePosition => "bytes",
SizeBytes => "size_bytes",
SizeBits => "size_bits",
ElementSizeBytes => "element_size_bytes",
ElementSizeBits => "element_size_bits",
Ty => "ty"
}
}
}
pub enum PackFieldAttribute {
IntEndiannes(IntegerEndianness),
BitPosition(BitsPositionParsed),
BytePosition(BitsPositionParsed),
SizeBits(usize),
ElementSizeBits(usize),
Ty(TyKind)
}
pub enum TyKind {
Enum
}
impl PackFieldAttribute {
pub fn parse(name: &str, val: &str) -> Result<Self, String> {
if name == PackFieldAttributeKind::IntEndiannes.get_attr_name() {
return Ok(PackFieldAttribute::IntEndiannes(IntegerEndianness::from_str(val).unwrap()));
}
if name == PackFieldAttributeKind::BitPosition.get_attr_name() {
let b = parse_position_val(val, 1)?;
return Ok(PackFieldAttribute::BitPosition(b));
}
if name == PackFieldAttributeKind::BytePosition.get_attr_name() {
let b = parse_position_val(val, 8)?;
return Ok(PackFieldAttribute::BytePosition(b));
}
if name == PackFieldAttributeKind::SizeBytes.get_attr_name() {
let b = parse_num(val)?;
return Ok(PackFieldAttribute::SizeBits(b * 8));
}
if name == PackFieldAttributeKind::SizeBits.get_attr_name() {
let b = parse_num(val)?;
return Ok(PackFieldAttribute::SizeBits(b));
}
if name == PackFieldAttributeKind::ElementSizeBytes.get_attr_name() {
let b = parse_num(val)?;
return Ok(PackFieldAttribute::ElementSizeBits(b * 8));
}
if name == PackFieldAttributeKind::ElementSizeBits.get_attr_name() {
let b = parse_num(val)?;
return Ok(PackFieldAttribute::ElementSizeBits(b));
}
if name == PackFieldAttributeKind::Ty.get_attr_name() && val == "enum" {
return Ok(PackFieldAttribute::Ty(TyKind::Enum));
}
Err(format!("Unsupported field attribute: {}, value {}", name, val))
}
pub fn parse_all(attributes: &[(String, String)]) -> Vec<Self> {
let mut r = vec![];
for &(ref name, ref val) in attributes {
if let Ok(attr) = Self::parse(name, val) {
r.push(attr)
}
}
r
}
}
pub fn parse_position_val(v: &str, multiplier: usize) -> Result<BitsPositionParsed, String> {
let v = v.trim();
if v.ends_with("..") {
let v = v.replace("..", "");
let n = parse_num(&v)?;
return Ok(BitsPositionParsed::Start(n * multiplier));
} else if v.ends_with(':') {
let v = v.replace(':', "");
let n = parse_num(&v)?;
return Ok(BitsPositionParsed::Start(n * multiplier));
} else if v.contains(':') || v.contains("..=") {
let s: Vec<_> = {
if v.contains(':') {
v.split(':').collect()
} else {
v.split("..=").collect()
}
};
if s.len() == 2 {
let start = parse_num(s[0])?;
let end = parse_num(s[1])?;
if multiplier > 1 {
return Ok(BitsPositionParsed::range_in_order(start * multiplier, ((end+1) * multiplier)-1));
} else {
return Ok(BitsPositionParsed::range_in_order(start, end));
}
}
} else if v.contains("..") {
let s: Vec<_> = v.split("..").collect();
if s.len() == 2 {
let start = parse_num(s[0])?;
let end = parse_num(s[1])?;
if end == 0 {
panic!("Ending cannot be 0 for exclusive ranges.");
}
if multiplier > 1 {
return Ok(BitsPositionParsed::range_in_order(start * multiplier, ((end-1) * multiplier)-1));
} else {
return Ok(BitsPositionParsed::range_in_order(start, end - 1));
}
}
} else {
let start = parse_num(v)?;
if multiplier > 1 {
return Ok(BitsPositionParsed::Range(start * multiplier, ((start+1) * multiplier)-1));
} else {
return Ok(BitsPositionParsed::Range(start, start));
}
}
panic!("Invalid bits position. Tried to parse: '{}'", v);
}
#[test]
fn test_parse_position_val() {
{
assert_eq!(BitsPositionParsed::Range(1, 1), parse_position_val("1", 1).unwrap());
assert_eq!(BitsPositionParsed::Range(8, 15), parse_position_val("1", 8).unwrap());
assert_eq!(BitsPositionParsed::Range(0, 7), parse_position_val("0", 8).unwrap());
}
{
assert_eq!(BitsPositionParsed::Start(1), parse_position_val("1..", 1).unwrap());
assert_eq!(BitsPositionParsed::Start(1), parse_position_val("1:", 1).unwrap());
}
{
assert_eq!(BitsPositionParsed::Range(1, 2), parse_position_val("1:2", 1).unwrap());
assert_eq!(BitsPositionParsed::Range(8, 23), parse_position_val("1:2", 8).unwrap());
assert_eq!(BitsPositionParsed::Range(0, 15), parse_position_val("0:1", 8).unwrap());
assert_eq!(BitsPositionParsed::Range(1, 2), parse_position_val("1..=2", 1).unwrap());
}
{
assert_eq!(BitsPositionParsed::Range(1, 2), parse_position_val("1..3", 1).unwrap());
assert_eq!(BitsPositionParsed::Range(8, 15), parse_position_val("1..3", 8).unwrap());
}
{
assert_eq!(BitsPositionParsed::Range(0, 7), parse_position_val("0", 8).unwrap());
assert_eq!(BitsPositionParsed::Range(8, 39), parse_position_val("1:4", 8).unwrap());
assert_eq!(BitsPositionParsed::Start(40), parse_position_val("5..", 8).unwrap());
}
}