ipmi_rs/storage/sdr/
get_sdr.rs1use std::num::NonZeroU16;
2
3use nonmax::NonMaxU8;
4
5use crate::connection::{IpmiCommand, Message, NetFn, ParseResponseError};
6
7use super::{Record, RecordId, RecordParseError};
8
9#[derive(Debug, Clone, Copy)]
17pub struct GetDeviceSdr {
18 reservation_id: Option<NonZeroU16>,
19 record_id: RecordId,
20 offset: u8,
21 bytes_to_read: Option<NonMaxU8>,
22}
23
24impl GetDeviceSdr {
25 pub fn new(reservation_id: Option<NonZeroU16>, record_id: RecordId) -> Self {
26 Self {
27 reservation_id,
28 record_id,
29 offset: 0,
31 bytes_to_read: None,
32 }
33 }
34}
35
36impl From<GetDeviceSdr> for Message {
37 fn from(value: GetDeviceSdr) -> Self {
38 let mut data = vec![0u8; 6];
39
40 data[0..2].copy_from_slice(
41 &value
42 .reservation_id
43 .map(NonZeroU16::get)
44 .unwrap_or(0)
45 .to_le_bytes(),
46 );
47
48 data[2..4].copy_from_slice(&value.record_id.value().to_le_bytes());
49 data[4] = value.offset;
50 data[5] = value.bytes_to_read.map(|v| v.get()).unwrap_or(0xFF);
51
52 Message::new_request(NetFn::Storage, 0x23, data)
53 }
54}
55
56impl IpmiCommand for GetDeviceSdr {
57 type Output = RecordInfo;
58
59 type Error = (RecordParseError, RecordId);
60
61 fn parse_response(
62 completion_code: crate::connection::CompletionCode,
63 data: &[u8],
64 ) -> Result<Self::Output, ParseResponseError<Self::Error>> {
65 Self::check_cc_success(completion_code)?;
66
67 if data.len() < 9 {
68 return Err(ParseResponseError::NotEnoughData);
69 }
70
71 let next_id = RecordId::new_raw(u16::from_le_bytes([data[0], data[1]]));
72
73 let res = RecordInfo::parse(data).map_err(|e| (e, next_id))?;
74
75 Ok(res)
76 }
77}
78
79#[derive(Debug, Clone)]
80pub struct RecordInfo {
81 pub next_entry: RecordId,
82 pub record: Record,
83}
84
85impl RecordInfo {
86 pub fn parse(data: &[u8]) -> Result<Self, RecordParseError> {
87 let next_entry = RecordId::new_raw(u16::from_le_bytes([data[0], data[1]]));
88 let data = &data[2..];
89 Record::parse(data).map(|record| Self { next_entry, record })
90 }
91}