Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 27 additions & 40 deletions cmd/net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,7 @@ fn net_ip(
};
let v = v.as_tuple()?;
assert_eq!(v.name(), "MacAddress");
let mut mac = [0; 6];
for (i, byte) in v[0].as_array()?.iter().enumerate() {
mac[i] = byte.as_base()?.as_u8().unwrap();
}
let mac = v.field::<[u8; 6]>(0)?;
print!("{}: ", "MAC address".bold());
for (i, byte) in mac.iter().enumerate() {
if i > 0 {
Expand Down Expand Up @@ -227,11 +224,8 @@ fn net_mac_table(
if let Ok(r) = r {
let s = r.as_struct()?;
assert_eq!(s.name(), "KszMacTableEntry");
let port = s["port"].as_base().unwrap().as_u16().unwrap();
let mut mac = [0; 6];
for (i, m) in s["mac"].as_array().unwrap().iter().enumerate() {
mac[i] = m.as_base().unwrap().as_u8().unwrap()
}
let port = s.field::<u16>("port").unwrap();
let mac = s.field::<[u8; 6]>("mac")?;
if mac == [0; 6] && port == 0xFFFF {
humility::msg!("Skipping empty MAC address");
} else {
Expand Down Expand Up @@ -290,16 +284,9 @@ fn net_status(
let s = v.as_struct()?;
assert_eq!(s.name(), "ManagementLinkStatus");

let to_bool_vec = |name| -> Result<Vec<bool>> {
Ok(s[name]
.as_array()?
.iter()
.map(|i| i.as_base().unwrap().as_bool().unwrap())
.collect())
};
let ksz_100base_fx = to_bool_vec("ksz8463_100base_fx_link_up")?;
let vsc_100base_fx = to_bool_vec("vsc85x2_100base_fx_link_up")?;
let vsc_sgmii = to_bool_vec("vsc85x2_sgmii_link_up")?;
let ksz_100base_fx: Vec<bool> = s.field("ksz8463_100base_fx_link_up")?;
let vsc_100base_fx: Vec<bool> = s.field("vsc85x2_100base_fx_link_up")?;
let vsc_sgmii: Vec<bool> = s.field("vsc85x2_sgmii_link_up")?;

let up_down = |b| {
if b { " UP ".green() } else { "DOWN".red() }
Expand Down Expand Up @@ -382,8 +369,8 @@ fn net_counters(
}

fn net_counters_table(s: &Struct) -> Result<()> {
let k_tx = s["ksz8463_tx"].as_array()?;
let k_rx = s["ksz8463_rx"].as_array()?;
let k_tx = s.field::<[_; 3]>("ksz8463_tx")?;
let k_rx = s.field::<[_; 3]>("ksz8463_rx")?;
let value = |k: &Struct, s: &str| {
let k = k[s].as_base().unwrap().as_u32().unwrap();
let out = format!("{:>6}", k);
Expand All @@ -407,8 +394,8 @@ fn net_counters_table(s: &Struct) -> Result<()> {
" |-----------|--------|--------|--------|--------|--------|--------|"
);
for i in 0..3 {
let k_tx = k_tx[i].as_struct()?;
let k_rx = k_rx[i].as_struct()?;
let k_tx = &k_tx[i];
let k_rx = &k_rx[i];
println!(
" | Port {} | {} | {} | {} | {} | {} | {} |",
i + 1,
Expand All @@ -426,12 +413,12 @@ fn net_counters_table(s: &Struct) -> Result<()> {

println!();

let v_tx = s["vsc85x2_tx"].as_array()?;
let v_rx = s["vsc85x2_rx"].as_array()?;
let v_mac_valid = s["vsc85x2_mac_valid"].as_base()?.as_bool().unwrap();
let v_tx = s.field::<[_; 2]>("vsc85x2_tx")?;
let v_rx = s.field::<[_; 2]>("vsc85x2_rx")?;
let v_mac_valid = s.field::<bool>("vsc85x2_mac_valid")?;

let value = |v: &Struct, s: &str| {
let v = v[s].as_base().unwrap().as_u16().unwrap();
let v = v.field::<u16>(s).unwrap();
let out = format!("{:>6}", v);
if v > 0 {
if s.contains("good") { out.green() } else { out.red() }
Expand All @@ -447,8 +434,8 @@ fn net_counters_table(s: &Struct) -> Result<()> {
println!(" | | Good | Bad | Good | Bad |");
println!(" |-----------------------------------------------------|");
for i in 0..2 {
let v_tx = v_tx[i].as_struct()?;
let v_rx = v_rx[i].as_struct()?;
let v_tx = &v_tx[i];
let v_rx = &v_rx[i];
if v_mac_valid {
println!(
" | Port {} | MAC | {} | {} | {} | {} |",
Expand Down Expand Up @@ -479,33 +466,33 @@ fn net_counters_table(s: &Struct) -> Result<()> {
}

fn net_counters_diagram(s: &Struct) -> Result<()> {
let k_tx = s["ksz8463_tx"].as_array()?;
let k_rx = s["ksz8463_rx"].as_array()?;
let value = |k: &Struct, s: &str| k[s].as_base().unwrap().as_u32().unwrap();
let k_tx = s.field::<[_; 3]>("ksz8463_tx")?;
let k_rx = s.field::<[_; 3]>("ksz8463_rx")?;
let value = |k: &Struct, s: &str| k.field::<u32>(s).unwrap();

let mut ksz_tx = [0; 3];
let mut ksz_rx = [0; 3];
for port in 0..3 {
let k_tx = k_tx[port].as_struct()?;
let k_rx = k_rx[port].as_struct()?;
let k_tx = &k_tx[port];
let k_rx = &k_rx[port];
for t in ["unicast", "broadcast", "multicast"] {
ksz_tx[port] += value(k_tx, t);
ksz_rx[port] += value(k_rx, t);
}
}

let v_tx = s["vsc85x2_tx"].as_array()?;
let v_rx = s["vsc85x2_rx"].as_array()?;
let v_mac_valid = s["vsc85x2_mac_valid"].as_base()?.as_bool().unwrap();
let value = |v: &Struct, s: &str| v[s].as_base().unwrap().as_u16().unwrap();
let v_tx = s.field::<[_; 3]>("vsc85x2_tx")?;
let v_rx = s.field::<[_; 3]>("vsc85x2_rx")?;
let v_mac_valid = s.field::<bool>("vsc85x2_mac_valid")?;
let value = |v: &Struct, s: &str| v.field::<u16>(s).unwrap();

let mut v_mac_tx = [0; 2];
let mut v_mac_rx = [0; 2];
let mut v_media_tx = [0; 2];
let mut v_media_rx = [0; 2];
for port in 0..2 {
let v_tx = v_tx[port].as_struct()?;
let v_rx = v_rx[port].as_struct()?;
let v_tx = &v_tx[port];
let v_rx = &v_rx[port];
if v_mac_valid {
v_mac_tx[port] = value(v_tx, "mac_good");
v_mac_rx[port] = value(v_rx, "mac_good");
Expand Down
57 changes: 56 additions & 1 deletion humility-core/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl Value {
Value::Struct(s) => {
v = s.get(f).ok_or_else(|| {
anyhow!(
"could not field field `{f}`; \
"could not find field `{f}`; \
available fields are {:?}",
s.members
.keys()
Expand Down Expand Up @@ -529,6 +529,14 @@ impl Struct {
{
self.members.get(name).map(Box::as_ref)
}

/// Loads the field with name `name` if it exists
pub fn field<T: Load>(&self, name: &str) -> Result<T> {
let Some(v) = self.members.get(name) else {
bail!("no such field {name}");
};
T::from_value(v)
}
}

/// Allows access to struct members using `s["foo"]`.
Expand Down Expand Up @@ -592,6 +600,14 @@ impl Tuple {
pub fn name(&self) -> &str {
self.0.as_str()
}

/// Loads the field with index `i` if it exists
pub fn field<T: Load>(&self, index: usize) -> Result<T> {
let Some(v) = self.1.get(index) else {
bail!("field {index} is not in range 0..{}", self.1.len());
};
T::from_value(v)
}
}

/// Allows the tuple to be treated like a slice, e.g. with `len()` and indexing.
Expand Down Expand Up @@ -1035,6 +1051,36 @@ impl Load for Enum {
}
}

impl Load for Struct {
fn from_value(v: &Value) -> Result<Self> {
if let Value::Struct(v) = v {
Ok(v.clone())
} else {
bail!("expected struct, got {v:?}");
}
}
}

impl Load for Tuple {
fn from_value(v: &Value) -> Result<Self> {
if let Value::Tuple(v) = v {
Ok(v.clone())
} else {
bail!("expected tuple, got {v:?}");
}
}
}

impl Load for Base {
fn from_value(v: &Value) -> Result<Self> {
if let Value::Base(v) = v {
Ok(v.clone())
} else {
bail!("expected base, got {v:?}");
}
}
}

impl Load for bool {
fn from_value(v: &Value) -> Result<Self> {
v.as_base()?.as_bool().ok_or_else(|| anyhow!("not a bool: {:?}", v))
Expand Down Expand Up @@ -1071,6 +1117,15 @@ impl Load for f32 {
}
}

impl Load for () {
fn from_value(v: &Value) -> Result<Self> {
match v.as_base()? {
Base::U0 => Ok(()),
b => bail!("expected U0, got base {b:?}"),
}
}
}

impl Load for Array {
fn from_value(v: &Value) -> Result<Self> {
if let Value::Array(v) = v {
Expand Down
20 changes: 2 additions & 18 deletions humility-spd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,24 +114,8 @@ pub fn spd_lookup(
out
}
Value::Struct(s) => {
let Some(Value::Array(a)) = s.get("spd_data") else {
bail!("expected `spd_data` to be an array");
};
let mut out = Vec::with_capacity(a.len());
for a in a.iter() {
let Value::Array(a) = a else {
bail!("expected array-of-arrays");
};
let mut chunk = Vec::with_capacity(a.len());
for v in a.iter() {
let Value::Base(Base::U8(b)) = v else {
bail!("expected `u8` array");
};
chunk.push(*b);
}
out.push(SpdData(chunk))
}
out
let out = s.field::<Vec<Vec<u8>>>("spd_data")?;
out.into_iter().map(SpdData).collect()
}
_ => bail!("expected `spd_data` to be an array or struct"),
};
Expand Down
Loading