use std::{fmt::Display, rc::Rc};
use convert_case::Boundary;
#[cfg(test)]
use device_driver_common::identifier::IdentifierType;
use device_driver_common::{
identifier::{All, Identifier, IdentifierRef, Operation, RuntimeType, Type},
span::{Span, SpanExt, Spanned},
specifiers::{
Access, AddressMode, AddressRange, BaseType, ByteOrder, Integer, NodeType, Repeat,
ResetValue, TypeConversion,
},
};
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Manifest {
pub description: String,
pub name: Spanned<Identifier<All>>,
pub default_access: Option<Access>,
pub config: DeviceConfig,
pub objects: Vec<Object>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl Manifest {
pub fn iter_objects_with_config_mut(&mut self) -> ObjectIterMut<'_> {
ObjectIterMut {
children: &mut self.objects,
parent: None,
collection_object_returned: false,
current_device_config: Rc::new(self.config.clone()),
}
}
pub fn iter_objects(&self) -> impl Iterator<Item = &Object> {
ObjectIter {
children: &self.objects,
parent: None,
collection_object_returned: false,
current_device_config: Rc::new(self.config.clone()),
}
.map(|(object, _)| object)
}
#[must_use]
pub fn iter_objects_with_config(&self) -> ObjectIter<'_> {
ObjectIter {
children: &self.objects,
parent: None,
collection_object_returned: false,
current_device_config: Rc::new(self.config.clone()),
}
}
pub fn iter_enums(&self) -> impl Iterator<Item = &'_ Enum> {
self.iter_objects_with_config().filter_map(|(o, _)| {
if let Object::Enum(e) = o {
Some(e)
} else {
None
}
})
}
pub fn iter_enums_with_config(&self) -> impl Iterator<Item = (&'_ Enum, Rc<DeviceConfig>)> {
self.iter_objects_with_config().filter_map(|(o, config)| {
if let Object::Enum(e) = o {
Some((e, config))
} else {
None
}
})
}
pub fn iter_devices_with_config(&self) -> impl Iterator<Item = (&'_ Device, Rc<DeviceConfig>)> {
self.iter_objects_with_config().filter_map(|(o, config)| {
if let Object::Device(d) = o {
Some((d, config))
} else {
None
}
})
}
}
#[derive(Default)]
pub struct ObjectIterMut<'a> {
children: &'a mut [Object],
parent: Option<Box<ObjectIterMut<'a>>>,
collection_object_returned: bool,
current_device_config: Rc<DeviceConfig>,
}
pub trait LendingIterator {
type Item<'a>
where
Self: 'a;
fn next(&mut self) -> Option<Self::Item<'_>>;
}
impl LendingIterator for ObjectIterMut<'_> {
type Item<'b>
= (&'b mut Object, Rc<DeviceConfig>)
where
Self: 'b;
fn next(&mut self) -> Option<Self::Item<'_>> {
if self.children.is_empty() {
match self.parent.take() {
Some(parent) => {
*self = *parent;
self.next()
}
None => None,
}
} else if self.children[0].child_objects_mut().is_empty() {
let (first, rest) = std::mem::take(&mut self.children)
.split_first_mut()
.expect("Already checked not empty");
self.children = rest;
Some((first, self.current_device_config.clone()))
} else if !self.collection_object_returned {
self.collection_object_returned = true;
let next_device_config = if let Some(new_config) = self.children[0].device_config() {
Rc::new(self.current_device_config.override_with(new_config))
} else {
self.current_device_config.clone()
};
Some((&mut self.children[0], next_device_config))
} else {
self.collection_object_returned = false;
let next_device_config = if let Some(new_config) = self.children[0].device_config() {
Rc::new(self.current_device_config.override_with(new_config))
} else {
self.current_device_config.clone()
};
let (first, rest) = std::mem::take(&mut self.children)
.split_first_mut()
.expect("Already checked not empty");
self.children = rest;
*self = ObjectIterMut {
children: first.child_objects_mut(),
parent: Some(Box::new(std::mem::take(self))),
collection_object_returned: false,
current_device_config: next_device_config,
};
self.next()
}
}
}
#[derive(Default)]
pub struct ObjectIter<'a> {
children: &'a [Object],
parent: Option<Box<ObjectIter<'a>>>,
collection_object_returned: bool,
current_device_config: Rc<DeviceConfig>,
}
impl<'a> Iterator for ObjectIter<'a> {
type Item = (&'a Object, Rc<DeviceConfig>);
fn next(&mut self) -> Option<Self::Item> {
let children = std::mem::take(&mut self.children);
match children.split_first() {
None => match self.parent.take() {
Some(parent) => {
*self = *parent;
self.next()
}
None => None,
},
Some((first, rest)) => {
self.children = rest;
if first.child_objects().is_empty() {
Some((first, self.current_device_config.clone()))
} else if !self.collection_object_returned {
self.collection_object_returned = true;
let next_device_config = if let Some(new_config) = first.device_config() {
Rc::new(self.current_device_config.override_with(new_config))
} else {
self.current_device_config.clone()
};
self.children = children;
Some((&children[0], next_device_config))
} else {
self.collection_object_returned = false;
let next_device_config = if let Some(new_config) = first.device_config() {
Rc::new(self.current_device_config.override_with(new_config))
} else {
self.current_device_config.clone()
};
*self = ObjectIter {
children: first.child_objects(),
parent: Some(Box::new(std::mem::take(self))),
collection_object_returned: false,
current_device_config: next_device_config,
};
self.next()
}
}
}
}
}
impl From<Device> for Manifest {
fn from(value: Device) -> Self {
let default_access = value.default_access;
Self {
description: String::new(),
name: value
.name
.value
.clone()
.cast_unchecked()
.with_span(value.name.span),
short_properties_span: value.short_properties_span,
properties_span: value.properties_span,
span: value.span,
objects: vec![Object::Device(value)],
default_access,
config: DeviceConfig::default(),
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Device {
pub description: String,
pub name: Spanned<Identifier<Type>>,
pub default_access: Option<Access>,
pub device_config: DeviceConfig,
pub objects: Vec<Object>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl Device {
pub fn iter_objects(&self) -> impl Iterator<Item = &Object> {
ObjectIter {
children: &self.objects,
parent: None,
collection_object_returned: false,
current_device_config: Rc::new(DeviceConfig::default()),
}
.map(|(object, _)| object)
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct DeviceConfig {
pub owner: Option<UniqueId>,
pub byte_order: Option<ByteOrder>,
pub register_address_type: Option<Spanned<Integer>>,
pub command_address_type: Option<Spanned<Integer>>,
pub buffer_address_type: Option<Spanned<Integer>>,
pub name_word_boundaries: Option<Vec<Boundary>>,
pub register_address_mode: Option<Spanned<AddressMode>>,
}
impl DeviceConfig {
#[must_use]
pub fn override_with(&self, other: &Self) -> DeviceConfig {
Self {
owner: other.owner.clone().or(self.owner.clone()),
byte_order: other.byte_order.or(self.byte_order),
register_address_type: other.register_address_type.or(self.register_address_type),
command_address_type: other.command_address_type.or(self.command_address_type),
buffer_address_type: other.buffer_address_type.or(self.buffer_address_type),
name_word_boundaries: other
.name_word_boundaries
.as_ref()
.or(self.name_word_boundaries.as_ref())
.cloned(),
register_address_mode: other.register_address_mode.or(self.register_address_mode),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Object {
Device(Device),
Block(Block),
Register(Register),
Command(Command),
Buffer(Buffer),
FieldSet(FieldSet),
Enum(Enum),
Extern(Extern),
Field(Field),
}
impl Object {
pub fn device_config(&self) -> Option<&DeviceConfig> {
match self {
Object::Device(device) => Some(&device.device_config),
_ => None,
}
}
pub fn child_objects_mut(&mut self) -> &mut [Object] {
match self {
Object::Device(device) => &mut device.objects,
Object::Block(block) => &mut block.objects,
_ => &mut [],
}
}
pub fn child_objects_vec(&mut self) -> Option<&mut Vec<Object>> {
match self {
Object::Device(device) => Some(&mut device.objects),
Object::Block(block) => Some(&mut block.objects),
_ => None,
}
}
pub fn child_objects(&self) -> &[Object] {
match self {
Object::Device(device) => &device.objects,
Object::Block(block) => &block.objects,
_ => &[],
}
}
pub fn name_mut(&mut self) -> &mut Identifier<RuntimeType> {
match self {
Object::Device(val) => val.name.as_runtime_type_mut(),
Object::Block(val) => val.name.as_runtime_type_mut(),
Object::Register(val) => val.name.as_runtime_type_mut(),
Object::Command(val) => val.name.as_runtime_type_mut(),
Object::Buffer(val) => val.name.as_runtime_type_mut(),
Object::FieldSet(val) => val.name.as_runtime_type_mut(),
Object::Enum(val) => val.name.as_runtime_type_mut(),
Object::Extern(val) => val.name.as_runtime_type_mut(),
Object::Field(val) => val.name.as_runtime_type_mut(),
}
}
pub fn name(&self) -> &Identifier<RuntimeType> {
match self {
Object::Device(val) => val.name.as_runtime_type(),
Object::Block(val) => val.name.as_runtime_type(),
Object::Register(val) => val.name.as_runtime_type(),
Object::Command(val) => val.name.as_runtime_type(),
Object::Buffer(val) => val.name.as_runtime_type(),
Object::FieldSet(val) => val.name.as_runtime_type(),
Object::Enum(val) => val.name.as_runtime_type(),
Object::Extern(val) => val.name.as_runtime_type(),
Object::Field(val) => val.name.as_runtime_type(),
}
}
pub fn name_span(&self) -> Span {
match self {
Object::Device(val) => val.name.span,
Object::Block(val) => val.name.span,
Object::Register(val) => val.name.span,
Object::Command(val) => val.name.span,
Object::Buffer(val) => val.name.span,
Object::FieldSet(val) => val.name.span,
Object::Enum(val) => val.name.span,
Object::Extern(val) => val.name.span,
Object::Field(val) => val.name.span,
}
}
pub fn address(&self) -> Option<Spanned<i128>> {
match self {
Object::Device(_) => None,
Object::Block(block) => Some(block.address_offset),
Object::Register(register) => Some(register.address),
Object::Command(command) => Some(command.address),
Object::Buffer(buffer) => Some(buffer.address),
Object::FieldSet(_) => None,
Object::Enum(_) => None,
Object::Extern(_) => None,
Object::Field(_) => None,
}
}
pub fn repeat(&self) -> Option<&Repeat> {
match self {
Object::Device(_) => None,
Object::Block(block) => block.repeat.as_ref(),
Object::Register(register) => register.repeat.as_ref(),
Object::Command(command) => command.repeat.as_ref(),
Object::Buffer(_) => None,
Object::FieldSet(_) => None,
Object::Enum(_) => None,
Object::Extern(_) => None,
Object::Field(field) => field.repeat.as_ref(),
}
}
pub fn repeat_mut(&mut self) -> Option<&mut Repeat> {
match self {
Object::Device(_) => None,
Object::Block(block) => block.repeat.as_mut(),
Object::Register(register) => register.repeat.as_mut(),
Object::Command(command) => command.repeat.as_mut(),
Object::Buffer(_) => None,
Object::FieldSet(_) => None,
Object::Enum(_) => None,
Object::Extern(_) => None,
Object::Field(field) => field.repeat.as_mut(),
}
}
pub fn as_field_set(&self) -> Option<&FieldSet> {
if let Self::FieldSet(v) = self {
Some(v)
} else {
None
}
}
pub fn as_field_set_mut(&mut self) -> Option<&mut FieldSet> {
if let Self::FieldSet(v) = self {
Some(v)
} else {
None
}
}
pub fn as_enum(&self) -> Option<&Enum> {
if let Self::Enum(v) = self {
Some(v)
} else {
None
}
}
pub fn allow_address_overlap(&self) -> bool {
match self {
Object::Device(_) => false,
Object::Block(_) => false,
Object::Register(register) => register.allow_address_overlap,
Object::Command(command) => command.allow_address_overlap,
Object::Buffer(_) => false,
Object::FieldSet(_) => false,
Object::Enum(_) => false,
Object::Extern(_) => false,
Object::Field(_) => false,
}
}
pub fn span(&self) -> Span {
match self {
Object::Device(val) => val.span,
Object::Block(val) => val.span,
Object::Register(val) => val.span,
Object::Command(val) => val.span,
Object::Buffer(val) => val.span,
Object::FieldSet(val) => val.span,
Object::Enum(val) => val.span,
Object::Extern(val) => val.span,
Object::Field(val) => val.span,
}
}
pub fn node_type(&self) -> NodeType {
match self {
Object::Device(_) => NodeType::Device,
Object::Block(_) => NodeType::Block,
Object::Register(_) => NodeType::Register,
Object::Command(_) => NodeType::Command,
Object::Buffer(_) => NodeType::Buffer,
Object::FieldSet(_) => NodeType::FieldSet,
Object::Enum(_) => NodeType::Enum,
Object::Extern(_) => NodeType::Extern,
Object::Field(_) => NodeType::Field,
}
}
pub fn fieldset_refs(&self) -> Vec<Spanned<IdentifierRef<Type>>> {
match self {
Object::Device(_) => Vec::new(),
Object::Block(_) => Vec::new(),
Object::Register(r) => vec![r.field_set_ref.clone()],
Object::Command(c) => [c.field_set_ref_in.clone(), c.field_set_ref_out.clone()]
.into_iter()
.flatten()
.collect(),
Object::Buffer(_) => Vec::new(),
Object::FieldSet(_) => Vec::new(),
Object::Enum(_) => Vec::new(),
Object::Extern(_) => Vec::new(),
Object::Field(_) => Vec::new(),
}
}
pub fn properties_span(&self) -> Option<Span> {
match self {
Object::Device(val) => val.properties_span,
Object::Block(val) => val.properties_span,
Object::Register(val) => val.properties_span,
Object::Command(val) => val.properties_span,
Object::Buffer(val) => val.properties_span,
Object::FieldSet(val) => val.properties_span,
Object::Enum(val) => val.properties_span,
Object::Extern(val) => val.properties_span,
Object::Field(val) => val.properties_span,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Block {
pub description: String,
pub name: Spanned<Identifier<All>>,
pub address_offset: Spanned<i128>,
pub repeat: Option<Repeat>,
pub objects: Vec<Object>,
pub default_access: Option<Access>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl Block {
pub fn iter_objects(&self) -> impl Iterator<Item = &Object> {
ObjectIter {
children: &self.objects,
parent: None,
collection_object_returned: false,
current_device_config: Rc::new(DeviceConfig::default()),
}
.map(|(object, _)| object)
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Register {
pub description: String,
pub name: Spanned<Identifier<Operation>>,
pub access: Option<Access>,
pub allow_address_overlap: bool,
pub address: Spanned<i128>,
pub reset_value: Option<Spanned<ResetValue>>,
pub repeat: Option<Repeat>,
pub field_set_ref: Spanned<IdentifierRef<Type>>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct FieldSet {
pub description: String,
pub name: Spanned<Identifier<Type>>,
pub size_bytes: Spanned<u32>,
pub byte_order: Option<ByteOrder>,
pub allow_bit_overlap: bool,
pub default_access: Option<Access>,
pub fields: Vec<Field>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl FieldSet {
pub fn size_bits(&self) -> u32 {
self.size_bytes.value * 8
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Field {
pub description: String,
pub name: Spanned<Identifier<All>>,
pub access: Option<Access>,
pub base_type: Spanned<BaseType>,
pub field_conversion: Option<TypeConversion>,
pub field_address: Spanned<AddressRange>,
pub repeat: Option<Repeat>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl Field {
#[must_use]
pub fn get_type_specifier_string(&self) -> String {
match &self.field_conversion {
Some(fc) => {
format!(
"{}:{}{}",
self.base_type,
fc.type_name.original(),
if fc.fallible { "?" } else { "" }
)
}
None => self.base_type.to_string(),
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Enum {
pub description: String,
pub name: Spanned<Identifier<Type>>,
pub variants: Vec<EnumVariant>,
pub base_type: Spanned<BaseType>,
pub size_bits: Option<u32>,
pub generation_style: Option<EnumGenerationStyle>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
impl Enum {
#[cfg(test)]
pub fn new(
description: String,
name: Spanned<Identifier<Type>>,
variants: Vec<EnumVariant>,
base_type: Spanned<BaseType>,
size_bits: Option<u32>,
span: Span,
) -> Self {
Self {
description,
name,
variants,
base_type,
size_bits,
generation_style: None,
short_properties_span: Span::empty(),
properties_span: None,
span,
}
}
#[cfg(test)]
pub fn new_with_style(
description: String,
name: Spanned<Identifier<Type>>,
variants: Vec<EnumVariant>,
base_type: Spanned<BaseType>,
size_bits: Option<u32>,
generation_style: EnumGenerationStyle,
span: Span,
) -> Self {
Self {
description,
name,
variants,
base_type,
size_bits,
generation_style: Some(generation_style),
short_properties_span: Span::empty(),
properties_span: None,
span,
}
}
pub fn iter_variants_with_discriminant(&self) -> impl Iterator<Item = (i128, &EnumVariant)> {
let mut next_discriminant = 0;
self.variants.iter().map(move |variant| {
if let Some(discriminant) = variant.value.specified_discriminant() {
next_discriminant = discriminant + 1;
(discriminant, variant)
} else {
let discriminant = next_discriminant;
next_discriminant += 1;
(discriminant, variant)
}
})
}
pub fn iter_variants_with_discriminant_mut(
&mut self,
) -> impl Iterator<Item = (i128, &mut EnumVariant)> {
let mut next_discriminant = 0;
self.variants.iter_mut().map(move |variant| {
if let Some(discriminant) = variant.value.specified_discriminant() {
next_discriminant = discriminant + 1;
(discriminant, variant)
} else {
let discriminant = next_discriminant;
next_discriminant += 1;
(discriminant, variant)
}
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum EnumGenerationStyle {
Fallible,
InfallibleWithinRange,
Fallback,
}
impl EnumGenerationStyle {
#[must_use]
pub fn is_fallible(&self) -> bool {
matches!(self, Self::Fallible)
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct EnumVariant {
pub description: String,
pub name: Spanned<Identifier<All>>,
pub value: EnumValue,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
pub enum EnumValue {
#[default]
Unspecified,
Specified(i128),
Default(i128),
UnspecifiedDefault,
CatchAll(i128),
UnspecifiedCatchAll,
}
impl EnumValue {
#[must_use]
pub fn is_default(&self) -> bool {
matches!(self, Self::Default(_) | Self::UnspecifiedDefault)
}
#[must_use]
pub fn is_catch_all(&self) -> bool {
matches!(self, Self::CatchAll(_) | Self::UnspecifiedCatchAll)
}
pub fn specified_discriminant(&self) -> Option<i128> {
match self {
Self::Unspecified | Self::UnspecifiedDefault | Self::UnspecifiedCatchAll => None,
Self::Specified(val) | EnumValue::Default(val) | EnumValue::CatchAll(val) => Some(*val),
}
}
pub fn specify(&mut self, num: i128) {
*self = match self {
EnumValue::Unspecified | EnumValue::Specified(_) => Self::Specified(num),
EnumValue::Default(_) | EnumValue::UnspecifiedDefault => Self::Default(num),
EnumValue::CatchAll(_) | EnumValue::UnspecifiedCatchAll => Self::CatchAll(num),
};
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Command {
pub description: String,
pub name: Spanned<Identifier<Operation>>,
pub address: Spanned<i128>,
pub allow_address_overlap: bool,
pub repeat: Option<Repeat>,
pub field_set_ref_in: Option<Spanned<IdentifierRef<Type>>>,
pub field_set_ref_out: Option<Spanned<IdentifierRef<Type>>>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Buffer {
pub description: String,
pub name: Spanned<Identifier<Operation>>,
pub access: Option<Access>,
pub address: Spanned<i128>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Extern {
pub description: String,
pub name: Spanned<Identifier<Type>>,
pub base_type: Spanned<BaseType>,
pub supports_infallible: bool,
pub size_bits: Option<Spanned<u64>>,
pub short_properties_span: Span,
pub properties_span: Option<Span>,
pub span: Span,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum UniqueId {
Object {
object_name: Spanned<Identifier<RuntimeType>>,
},
Field {
parent_id: Box<UniqueId>,
field_name: Spanned<Identifier<RuntimeType>>,
},
Variant {
parent_id: Box<UniqueId>,
variant_name: Spanned<Identifier<RuntimeType>>,
},
}
impl UniqueId {
#[must_use]
pub fn span(&self) -> Span {
match self {
UniqueId::Object { object_name } => object_name.span,
UniqueId::Field { field_name, .. } => field_name.span,
UniqueId::Variant { variant_name, .. } => variant_name.span,
}
}
pub fn identifier(&self) -> &Identifier<RuntimeType> {
match self {
UniqueId::Object { object_name } => object_name,
UniqueId::Field { field_name, .. } => field_name,
UniqueId::Variant { variant_name, .. } => variant_name,
}
}
#[cfg(test)]
pub fn new_test<T: IdentifierType>(identifier: Identifier<T>) -> Self {
use device_driver_common::span::SpanExt;
Self::Object {
object_name: identifier.to_runtime_type().with_dummy_span(),
}
}
}
impl Display for UniqueId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UniqueId::Object { object_name } => write!(f, "{}", object_name.original()),
UniqueId::Field {
parent_id,
field_name,
} => write!(f, "{parent_id} {{ {} }}", field_name.original()),
UniqueId::Variant {
parent_id,
variant_name,
} => write!(f, "{parent_id} {{ {} }}", variant_name.original()),
}
}
}
pub trait Unique {
type Metadata;
fn id(&self) -> UniqueId
where
Self::Metadata: Empty;
fn id_with(&self, meta: Self::Metadata) -> UniqueId;
fn has_id(&self, id: &UniqueId) -> bool
where
Self::Metadata: Empty;
fn has_id_with(&self, meta: Self::Metadata, id: &UniqueId) -> bool {
self.id_with(meta) == *id
}
}
pub trait Empty {}
impl Empty for () {}
macro_rules! impl_unique_object {
($t:ty) => {
impl Unique for $t {
type Metadata = ();
fn id(&self) -> UniqueId {
UniqueId::Object {
object_name: self
.name
.value
.clone()
.to_runtime_type()
.with_span(self.name.span),
}
}
fn id_with(&self, _: Self::Metadata) -> UniqueId {
self.id()
}
fn has_id(&self, id: &UniqueId) -> bool {
match id {
UniqueId::Object { object_name } => {
self.name.as_runtime_type() == &object_name.value
}
_ => false,
}
}
}
};
}
impl_unique_object!(Device);
impl_unique_object!(Register);
impl_unique_object!(Command);
impl_unique_object!(Buffer);
impl_unique_object!(Block);
impl_unique_object!(Enum);
impl_unique_object!(FieldSet);
impl_unique_object!(Extern);
impl Unique for Field {
type Metadata = UniqueId;
fn id(&self) -> UniqueId {
unreachable!()
}
fn id_with(&self, parent: Self::Metadata) -> UniqueId {
UniqueId::Field {
parent_id: Box::new(parent),
field_name: self
.name
.value
.clone()
.to_runtime_type()
.with_span(self.name.span),
}
}
fn has_id(&self, _id: &UniqueId) -> bool {
unreachable!()
}
}
impl Unique for EnumVariant {
type Metadata = UniqueId;
fn id(&self) -> UniqueId {
unreachable!()
}
fn id_with(&self, parent: Self::Metadata) -> UniqueId {
UniqueId::Variant {
parent_id: Box::new(parent),
variant_name: self
.name
.value
.clone()
.to_runtime_type()
.with_span(self.name.span),
}
}
fn has_id(&self, _id: &UniqueId) -> bool {
unreachable!()
}
}
impl Unique for Object {
type Metadata = ();
fn id(&self) -> UniqueId {
match self {
Object::Device(val) => val.id(),
Object::Block(val) => val.id(),
Object::Register(val) => val.id(),
Object::Command(val) => val.id(),
Object::Buffer(val) => val.id(),
Object::FieldSet(val) => val.id(),
Object::Enum(val) => val.id(),
Object::Extern(val) => val.id(),
Object::Field(_) => unimplemented!(),
}
}
fn id_with(&self, (): Self::Metadata) -> UniqueId {
self.id()
}
fn has_id(&self, id: &UniqueId) -> bool {
match self {
Object::Device(val) => val.has_id(id),
Object::Block(val) => val.has_id(id),
Object::Register(val) => val.has_id(id),
Object::Command(val) => val.has_id(id),
Object::Buffer(val) => val.has_id(id),
Object::FieldSet(val) => val.has_id(id),
Object::Enum(val) => val.has_id(id),
Object::Extern(val) => val.has_id(id),
Object::Field(_) => unimplemented!(),
}
}
}
#[cfg(test)]
mod tests {
use device_driver_common::span::SpanExt;
use super::*;
#[test]
fn iter_works() {
const NAME_ORDER: &[&str] = &["a", "b", "c", "d"];
let mut manifest = Manifest {
description: Default::default(),
name: Default::default(),
objects: vec![
Object::Device(Device {
description: String::new(),
name: Identifier::try_parse("a").unwrap().with_dummy_span(),
objects: vec![
Object::Extern(Extern {
name: Identifier::try_parse("b").unwrap().with_dummy_span(),
..Default::default()
}),
Object::Extern(Extern {
name: Identifier::try_parse("c").unwrap().with_dummy_span(),
..Default::default()
}),
],
..Default::default()
}),
Object::Extern(Extern {
name: Identifier::try_parse("d").unwrap().with_dummy_span(),
..Default::default()
}),
],
..Default::default()
};
let names: Vec<_> = manifest
.iter_objects()
.map(|o| o.name().original())
.collect();
assert_eq!(&names, NAME_ORDER);
let mut names = Vec::new();
let mut lender = manifest.iter_objects_with_config_mut();
while let Some((object, _)) = lender.next() {
names.push(object.name().original().to_string());
}
assert_eq!(&names, NAME_ORDER);
}
#[test]
fn correct_integer_size_bits() {
assert_eq!(Integer::U8.bits_required(0, 0), 0);
assert_eq!(Integer::U8.bits_required(0, 1), 1);
assert_eq!(Integer::U8.bits_required(0, 2), 2);
assert_eq!(Integer::U8.bits_required(0, 3), 2);
assert_eq!(Integer::U8.bits_required(0, 4), 3);
assert_eq!(Integer::I8.bits_required(0, 0), 0);
assert_eq!(Integer::I8.bits_required(-1, 0), 1);
assert_eq!(Integer::I8.bits_required(-1, 1), 2);
assert_eq!(Integer::I8.bits_required(0, 1), 2);
assert_eq!(Integer::I8.bits_required(-2, 1), 2);
assert_eq!(Integer::I8.bits_required(0, 2), 3);
assert_eq!(Integer::I8.bits_required(-128, 0), 8);
assert_eq!(Integer::I8.bits_required(-129, 0), 9);
assert_eq!(Integer::I8.bits_required(0, 127), 8);
assert_eq!(Integer::I8.bits_required(0, 128), 9);
assert_eq!(Integer::I8.bits_required(-16, 15), 5);
assert_eq!(Integer::I8.bits_required(-16, 16), 6);
assert_eq!(Integer::I8.bits_required(-17, 15), 6);
}
}