use super::{
access::Access, deserialize_int, deserialize_int_opt, field::Field, peripheral::Peripheral,
Device,
};
use anyhow::{anyhow, Result};
use indexmap::IndexMap;
use serde::{Deserialize, Deserializer};
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum RegisterTree {
Register(Register),
Cluster(Cluster),
}
#[non_exhaustive]
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Cluster {
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub dim: Option<u32>,
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub dim_increment: Option<u32>,
pub name: String,
pub alternate_cluster: Option<String>,
#[serde(default)]
pub description: String,
#[serde(deserialize_with = "deserialize_int")]
pub address_offset: u32,
#[serde(default, deserialize_with = "deserialize_register_tree")]
pub(crate) register: IndexMap<String, RegisterTree>,
#[serde(skip)]
pub(crate) variants: Vec<String>,
}
#[non_exhaustive]
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Register {
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub dim: Option<u32>,
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub dim_increment: Option<u32>,
pub name: String,
#[serde(default)]
pub description: String,
pub alternate_register: Option<String>,
#[serde(deserialize_with = "deserialize_int")]
pub address_offset: u32,
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub size: Option<u32>,
pub access: Option<Access>,
#[serde(default, deserialize_with = "deserialize_int_opt")]
pub reset_value: Option<u32>,
pub(crate) fields: Option<Fields>,
#[serde(skip)]
pub(crate) variants: Vec<String>,
}
#[non_exhaustive]
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Fields {
pub(crate) field: Vec<Field>,
}
impl Register {
pub fn field(&mut self, name: &str) -> &mut Field {
self.fields.as_mut().unwrap().field.iter_mut().find(|field| field.name == name).unwrap()
}
pub fn add_field(&mut self, field: Field) {
self.fields.get_or_insert_with(Default::default).field.push(field);
}
pub fn new_field(&mut self, f: impl FnOnce(&mut Field)) {
let mut field = Field::default();
f(&mut field);
self.add_field(field);
}
pub fn remove_field(&mut self, name: &str) -> Field {
let index = self
.fields
.as_ref()
.unwrap()
.field
.iter()
.position(|field| field.name == name)
.unwrap();
self.fields.as_mut().unwrap().field.remove(index)
}
pub(crate) fn size(
&self,
device: &Device,
peripheral: &Peripheral,
parent: Option<&Peripheral>,
) -> Result<u32> {
self.size
.or(peripheral.size)
.or_else(|| parent.and_then(|peripheral| peripheral.size))
.or(device.size)
.ok_or_else(|| anyhow!("missing register size"))
}
pub(crate) fn reset_value(
&self,
device: &Device,
peripheral: &Peripheral,
parent: Option<&Peripheral>,
) -> Result<u32> {
self.reset_value
.or(peripheral.reset_value)
.or_else(|| parent.and_then(|peripheral| peripheral.reset_value))
.or(device.reset_value)
.ok_or_else(|| anyhow!("missing reset value"))
}
pub(crate) fn access(
&self,
device: &Device,
peripheral: &Peripheral,
parent: Option<&Peripheral>,
) -> Option<Access> {
self.access
.or(peripheral.access)
.or_else(|| parent.and_then(|peripheral| peripheral.access))
.or(device.access)
}
}
impl RegisterTree {
#[track_caller]
pub(crate) fn unwrap_register_ref(&self) -> &Register {
match self {
RegisterTree::Register(register) => register,
RegisterTree::Cluster(_) => panic!(
"called `RegisterTree::unwrap_register_ref()` on a `&RegisterTree::Cluster` value"
),
}
}
pub(crate) fn unwrap_register_mut(&mut self) -> &mut Register {
match self {
RegisterTree::Register(register) => register,
RegisterTree::Cluster(_) => panic!(
"called `RegisterTree::unwrap_register_mut()` on a `&mut RegisterTree::Cluster` \
value"
),
}
}
#[track_caller]
pub(crate) fn unwrap_register(self) -> Register {
match self {
RegisterTree::Register(register) => register,
RegisterTree::Cluster(_) => panic!(
"called `RegisterTree::unwrap_register()` on a `RegisterTree::Cluster` value"
),
}
}
#[track_caller]
pub(crate) fn unwrap_cluster_ref(&self) -> &Cluster {
match self {
RegisterTree::Cluster(cluster) => cluster,
RegisterTree::Register(_) => panic!(
"called `RegisterTree::unwrap_cluster_ref()` on a `&RegisterTree::Register` value"
),
}
}
#[track_caller]
pub(crate) fn unwrap_cluster_mut(&mut self) -> &mut Cluster {
match self {
RegisterTree::Cluster(cluster) => cluster,
RegisterTree::Register(_) => panic!(
"called `RegisterTree::unwrap_cluster_mut()` on a `&mut RegisterTree::Register` \
value"
),
}
}
}
pub(crate) fn tree_reg<'a, 'b>(
tree: &'a mut IndexMap<String, RegisterTree>,
path: &'b str,
) -> &'a mut Register {
let mut path = path.splitn(2, '/');
let name = path.next().unwrap();
for node in tree.values_mut() {
match node {
RegisterTree::Register(register) => {
if register.name == name {
if path.next().is_none() {
return register;
}
panic!("extra segments at the tail");
}
}
RegisterTree::Cluster(cluster) => {
if cluster.name == name {
return tree_reg(&mut cluster.register, path.next().unwrap());
}
}
}
}
panic!("register not found")
}
pub(crate) fn tree_remove_reg(tree: &mut IndexMap<String, RegisterTree>, path: &str) -> Register {
let mut path = path.splitn(2, '/');
let name = path.next().unwrap();
for key in tree.keys().cloned().collect::<Vec<_>>() {
match tree.get_mut(&key).unwrap() {
RegisterTree::Register(register) => {
if register.name == name {
if path.next().is_none() {
return tree.remove(&key).unwrap().unwrap_register();
}
panic!("extra segments at the tail");
}
}
RegisterTree::Cluster(cluster) => {
if cluster.name == name {
return tree_remove_reg(&mut cluster.register, path.next().unwrap());
}
}
}
}
panic!("register not found");
}
fn deserialize_register_tree<'de, D>(
deserializer: D,
) -> Result<IndexMap<String, RegisterTree>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = IndexMap::new();
for register in Vec::<Register>::deserialize(deserializer)? {
map.insert(register.name.clone(), RegisterTree::Register(register));
}
Ok(map)
}