|
|
|
@ -24,12 +24,15 @@
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
use crate::engine::{
|
|
|
|
|
use crate::{
|
|
|
|
|
engine::{
|
|
|
|
|
mem::ByteStack,
|
|
|
|
|
storage::{
|
|
|
|
|
v1::header_impl::{FileScope, FileSpecifier, FileSpecifierVersion, HostRunMode},
|
|
|
|
|
versions::{self, DriverVersion, ServerVersion},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
util,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -44,7 +47,7 @@ use crate::engine::{
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
|
pub struct MetadataRecord {
|
|
|
|
|
pub struct GRMetadataRecord {
|
|
|
|
|
server_version: ServerVersion,
|
|
|
|
|
driver_version: DriverVersion,
|
|
|
|
|
file_scope: FileScope,
|
|
|
|
@ -52,7 +55,7 @@ pub struct MetadataRecord {
|
|
|
|
|
file_spec_id: FileSpecifierVersion,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MetadataRecord {
|
|
|
|
|
impl GRMetadataRecord {
|
|
|
|
|
pub const fn new(
|
|
|
|
|
server_version: ServerVersion,
|
|
|
|
|
driver_version: DriverVersion,
|
|
|
|
@ -83,8 +86,8 @@ impl MetadataRecord {
|
|
|
|
|
pub const fn file_spec_id(&self) -> FileSpecifierVersion {
|
|
|
|
|
self.file_spec_id
|
|
|
|
|
}
|
|
|
|
|
pub const fn encode(&self) -> MetadataRecordRaw {
|
|
|
|
|
MetadataRecordRaw::new_full(
|
|
|
|
|
pub const fn encoded(&self) -> GRMetadataRecordRaw {
|
|
|
|
|
GRMetadataRecordRaw::new_full(
|
|
|
|
|
self.server_version(),
|
|
|
|
|
self.driver_version(),
|
|
|
|
|
self.file_scope(),
|
|
|
|
@ -94,15 +97,15 @@ impl MetadataRecord {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct MetadataRecordRaw {
|
|
|
|
|
pub struct GRMetadataRecordRaw {
|
|
|
|
|
pub(super) data: ByteStack<32>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MetadataRecordRaw {
|
|
|
|
|
impl GRMetadataRecordRaw {
|
|
|
|
|
/// Decodes a given metadata record, validating all data for correctness.
|
|
|
|
|
///
|
|
|
|
|
/// WARNING: That means you need to do contextual validation! This function is not aware of any context
|
|
|
|
|
pub fn decode_from_bytes(data: [u8; 32]) -> Option<MetadataRecord> {
|
|
|
|
|
/// **☢ WARNING ☢: This only decodes; it doesn't validate expected values!**
|
|
|
|
|
pub fn decode(data: [u8; 32]) -> Option<GRMetadataRecord> {
|
|
|
|
|
let data = ByteStack::new(data);
|
|
|
|
|
let server_version =
|
|
|
|
|
ServerVersion::__new(u64::from_le(data.read_qword(Self::MDR_OFFSET_P0)));
|
|
|
|
@ -112,7 +115,7 @@ impl MetadataRecordRaw {
|
|
|
|
|
let file_spec = FileSpecifier::try_new(u32::from_le(data.read_dword(Self::MDR_OFFSET_P3)))?;
|
|
|
|
|
let file_spec_id =
|
|
|
|
|
FileSpecifierVersion::__new(u32::from_le(data.read_dword(Self::MDR_OFFSET_P4)));
|
|
|
|
|
Some(MetadataRecord::new(
|
|
|
|
|
Some(GRMetadataRecord::new(
|
|
|
|
|
server_version,
|
|
|
|
|
driver_version,
|
|
|
|
|
file_scope,
|
|
|
|
@ -122,7 +125,7 @@ impl MetadataRecordRaw {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MetadataRecordRaw {
|
|
|
|
|
impl GRMetadataRecordRaw {
|
|
|
|
|
const MDR_OFFSET_P0: usize = 0;
|
|
|
|
|
const MDR_OFFSET_P1: usize = sizeof!(u64);
|
|
|
|
|
const MDR_OFFSET_P2: usize = Self::MDR_OFFSET_P1 + sizeof!(u64);
|
|
|
|
@ -180,7 +183,7 @@ impl MetadataRecordRaw {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MetadataRecordRaw {
|
|
|
|
|
impl GRMetadataRecordRaw {
|
|
|
|
|
pub const fn read_p0_server_version(&self) -> ServerVersion {
|
|
|
|
|
ServerVersion::__new(self.data.read_qword(Self::MDR_OFFSET_P0))
|
|
|
|
|
}
|
|
|
|
@ -208,216 +211,182 @@ impl MetadataRecordRaw {
|
|
|
|
|
- 04B: Host setting version ID
|
|
|
|
|
- 04B: Host run mode
|
|
|
|
|
- 08B: Host startup counter
|
|
|
|
|
- 08B: Host name length
|
|
|
|
|
- ??B: Host name
|
|
|
|
|
- 01B: Host name length
|
|
|
|
|
- 255B: Host name
|
|
|
|
|
= 304B
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
pub type HRConstSectionRaw = [u8; 56];
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
|
pub struct HostRecord {
|
|
|
|
|
hr_cr: HRConstSection,
|
|
|
|
|
host_name: Box<[u8]>,
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
|
pub struct GRHostRecord {
|
|
|
|
|
epoch_time: u128,
|
|
|
|
|
uptime: u128,
|
|
|
|
|
setting_version: u32,
|
|
|
|
|
run_mode: HostRunMode,
|
|
|
|
|
startup_counter: u64,
|
|
|
|
|
hostname_len: u8,
|
|
|
|
|
hostname_raw: [u8; 255],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HostRecord {
|
|
|
|
|
pub fn new(hr_cr: HRConstSection, host_name: Box<[u8]>) -> Self {
|
|
|
|
|
Self { hr_cr, host_name }
|
|
|
|
|
}
|
|
|
|
|
pub fn hr_cr(&self) -> &HRConstSection {
|
|
|
|
|
&self.hr_cr
|
|
|
|
|
}
|
|
|
|
|
pub fn host_name(&self) -> &[u8] {
|
|
|
|
|
self.host_name.as_ref()
|
|
|
|
|
}
|
|
|
|
|
pub fn encode(&self) -> HostRecordRaw {
|
|
|
|
|
HostRecordRaw::new(
|
|
|
|
|
self.hr_cr().host_epoch_time(),
|
|
|
|
|
self.hr_cr().host_uptime(),
|
|
|
|
|
self.hr_cr().host_setting_version_id(),
|
|
|
|
|
self.hr_cr().host_run_mode(),
|
|
|
|
|
self.hr_cr().host_startup_counter(),
|
|
|
|
|
self.host_name().into(),
|
|
|
|
|
)
|
|
|
|
|
impl GRHostRecord {
|
|
|
|
|
pub fn decode(bytes: [u8; sizeof!(GRHostRecordRaw)]) -> Option<Self> {
|
|
|
|
|
let ns = ByteStack::new(bytes);
|
|
|
|
|
let epoch_time = u128::from_le(ns.read_xmmword(GRHostRecordRaw::GRHR_OFFSET_P0));
|
|
|
|
|
let uptime = u128::from_le(ns.read_xmmword(GRHostRecordRaw::GRHR_OFFSET_P1));
|
|
|
|
|
let setting_version = u32::from_le(ns.read_dword(GRHostRecordRaw::GRHR_OFFSET_P2));
|
|
|
|
|
let run_mode = HostRunMode::try_new_with_val(u32::from_le(
|
|
|
|
|
ns.read_dword(GRHostRecordRaw::GRHR_OFFSET_P3),
|
|
|
|
|
))?;
|
|
|
|
|
let startup_counter = u64::from_le(ns.read_qword(GRHostRecordRaw::GRHR_OFFSET_P4));
|
|
|
|
|
let host_name_len = ns.read_byte(GRHostRecordRaw::GRHR_OFFSET_P5);
|
|
|
|
|
let host_name_raw =
|
|
|
|
|
util::copy_slice_to_array(&ns.slice()[GRHostRecordRaw::GRHR_OFFSET_P6..]);
|
|
|
|
|
Some(Self::new(
|
|
|
|
|
epoch_time,
|
|
|
|
|
uptime,
|
|
|
|
|
setting_version,
|
|
|
|
|
run_mode,
|
|
|
|
|
startup_counter,
|
|
|
|
|
host_name_len,
|
|
|
|
|
host_name_raw,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
|
pub struct HRConstSection {
|
|
|
|
|
host_epoch_time: u128,
|
|
|
|
|
host_uptime: u128,
|
|
|
|
|
host_setting_version_id: u32,
|
|
|
|
|
host_run_mode: HostRunMode,
|
|
|
|
|
host_startup_counter: u64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HRConstSection {
|
|
|
|
|
impl GRHostRecord {
|
|
|
|
|
pub const fn new(
|
|
|
|
|
host_epoch_time: u128,
|
|
|
|
|
host_uptime: u128,
|
|
|
|
|
host_setting_version_id: u32,
|
|
|
|
|
host_run_mode: HostRunMode,
|
|
|
|
|
host_startup_counter: u64,
|
|
|
|
|
epoch_time: u128,
|
|
|
|
|
uptime: u128,
|
|
|
|
|
setting_version: u32,
|
|
|
|
|
run_mode: HostRunMode,
|
|
|
|
|
startup_counter: u64,
|
|
|
|
|
hostname_len: u8,
|
|
|
|
|
hostname: [u8; 255],
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
host_epoch_time,
|
|
|
|
|
host_uptime,
|
|
|
|
|
host_setting_version_id,
|
|
|
|
|
host_run_mode,
|
|
|
|
|
host_startup_counter,
|
|
|
|
|
epoch_time,
|
|
|
|
|
uptime,
|
|
|
|
|
setting_version,
|
|
|
|
|
run_mode,
|
|
|
|
|
startup_counter,
|
|
|
|
|
hostname_len,
|
|
|
|
|
hostname_raw: hostname,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub const fn host_epoch_time(&self) -> u128 {
|
|
|
|
|
self.host_epoch_time
|
|
|
|
|
pub fn epoch_time(&self) -> u128 {
|
|
|
|
|
self.epoch_time
|
|
|
|
|
}
|
|
|
|
|
pub const fn host_uptime(&self) -> u128 {
|
|
|
|
|
self.host_uptime
|
|
|
|
|
pub fn uptime(&self) -> u128 {
|
|
|
|
|
self.uptime
|
|
|
|
|
}
|
|
|
|
|
pub const fn host_setting_version_id(&self) -> u32 {
|
|
|
|
|
self.host_setting_version_id
|
|
|
|
|
pub fn setting_version(&self) -> u32 {
|
|
|
|
|
self.setting_version
|
|
|
|
|
}
|
|
|
|
|
pub const fn host_run_mode(&self) -> HostRunMode {
|
|
|
|
|
self.host_run_mode
|
|
|
|
|
pub fn run_mode(&self) -> HostRunMode {
|
|
|
|
|
self.run_mode
|
|
|
|
|
}
|
|
|
|
|
pub const fn host_startup_counter(&self) -> u64 {
|
|
|
|
|
self.host_startup_counter
|
|
|
|
|
pub fn startup_counter(&self) -> u64 {
|
|
|
|
|
self.startup_counter
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct HostRecordRaw {
|
|
|
|
|
pub(super) data: ByteStack<{ sizeof!(HRConstSectionRaw) }>,
|
|
|
|
|
pub(super) host_name: Box<[u8]>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HostRecordRaw {
|
|
|
|
|
pub const fn empty_buffer_const_section() -> [u8; sizeof!(HRConstSectionRaw)] {
|
|
|
|
|
[0u8; sizeof!(HRConstSectionRaw)]
|
|
|
|
|
}
|
|
|
|
|
/// Decodes and validates the [`HRConstSection`] of a [`HostRecord`]. Use the returned result to construct this
|
|
|
|
|
pub fn decode_from_bytes_const_sec(data: HRConstSectionRaw) -> Option<(HRConstSection, usize)> {
|
|
|
|
|
let s = ByteStack::new(data);
|
|
|
|
|
let host_epoch_time = s.read_xmmword(Self::HR_OFFSET_P0);
|
|
|
|
|
if host_epoch_time > crate::util::os::get_epoch_time() {
|
|
|
|
|
// and what? we have a file from the future. Einstein says hi. (ok, maybe the host time is incorrect)
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let host_uptime = s.read_xmmword(Self::HR_OFFSET_P1);
|
|
|
|
|
let host_setting_version_id = s.read_dword(Self::HR_OFFSET_P2A);
|
|
|
|
|
let host_setting_run_mode =
|
|
|
|
|
HostRunMode::try_new_with_val(s.read_dword(Self::HR_OFFSET_P2B))?;
|
|
|
|
|
let host_startup_counter = s.read_qword(Self::HR_OFFSET_P3);
|
|
|
|
|
let host_name_length = s.read_qword(Self::HR_OFFSET_P4);
|
|
|
|
|
if host_name_length as usize > usize::MAX {
|
|
|
|
|
// too large for us to load. per DNS standards this shouldn't be more than 255 but who knows, some people like it wild
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
Some((
|
|
|
|
|
HRConstSection::new(
|
|
|
|
|
host_epoch_time,
|
|
|
|
|
host_uptime,
|
|
|
|
|
host_setting_version_id,
|
|
|
|
|
host_setting_run_mode,
|
|
|
|
|
host_startup_counter,
|
|
|
|
|
),
|
|
|
|
|
host_name_length as usize,
|
|
|
|
|
))
|
|
|
|
|
pub fn hostname_len(&self) -> u8 {
|
|
|
|
|
self.hostname_len
|
|
|
|
|
}
|
|
|
|
|
pub fn decoded(&self) -> HostRecord {
|
|
|
|
|
HostRecord::new(
|
|
|
|
|
HRConstSection::new(
|
|
|
|
|
self.read_p0_epoch_time(),
|
|
|
|
|
self.read_p1_uptime(),
|
|
|
|
|
self.read_p2a_setting_version_id(),
|
|
|
|
|
self.read_p2b_run_mode(),
|
|
|
|
|
self.read_p3_startup_counter(),
|
|
|
|
|
),
|
|
|
|
|
self.host_name.clone(),
|
|
|
|
|
pub fn hostname_raw(&self) -> [u8; 255] {
|
|
|
|
|
self.hostname_raw
|
|
|
|
|
}
|
|
|
|
|
pub fn encoded(&self) -> GRHostRecordRaw {
|
|
|
|
|
GRHostRecordRaw::new(
|
|
|
|
|
self.epoch_time(),
|
|
|
|
|
self.uptime(),
|
|
|
|
|
self.setting_version(),
|
|
|
|
|
self.run_mode(),
|
|
|
|
|
self.startup_counter(),
|
|
|
|
|
self.hostname_len(),
|
|
|
|
|
self.hostname_raw(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HostRecordRaw {
|
|
|
|
|
const HR_OFFSET_P0: usize = 0;
|
|
|
|
|
const HR_OFFSET_P1: usize = sizeof!(u128);
|
|
|
|
|
const HR_OFFSET_P2A: usize = Self::HR_OFFSET_P1 + sizeof!(u128);
|
|
|
|
|
const HR_OFFSET_P2B: usize = Self::HR_OFFSET_P2A + sizeof!(u32);
|
|
|
|
|
const HR_OFFSET_P3: usize = Self::HR_OFFSET_P2B + sizeof!(u32);
|
|
|
|
|
const HR_OFFSET_P4: usize = Self::HR_OFFSET_P3 + sizeof!(u64);
|
|
|
|
|
const _ENSURE: () = assert!(Self::HR_OFFSET_P4 == sizeof!(HRConstSectionRaw) - sizeof!(u64));
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
|
pub struct GRHostRecordRaw {
|
|
|
|
|
pub(super) data: ByteStack<304>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl GRHostRecordRaw {
|
|
|
|
|
const GRHR_OFFSET_P0: usize = 0;
|
|
|
|
|
const GRHR_OFFSET_P1: usize = sizeof!(u128);
|
|
|
|
|
const GRHR_OFFSET_P2: usize = Self::GRHR_OFFSET_P1 + sizeof!(u128);
|
|
|
|
|
const GRHR_OFFSET_P3: usize = Self::GRHR_OFFSET_P2 + sizeof!(u32);
|
|
|
|
|
const GRHR_OFFSET_P4: usize = Self::GRHR_OFFSET_P3 + sizeof!(u32);
|
|
|
|
|
const GRHR_OFFSET_P5: usize = Self::GRHR_OFFSET_P4 + sizeof!(u64);
|
|
|
|
|
const GRHR_OFFSET_P6: usize = Self::GRHR_OFFSET_P5 + 1;
|
|
|
|
|
const _ENSURE: () = assert!(Self::GRHR_OFFSET_P6 == sizeof!(Self) - 255);
|
|
|
|
|
pub fn new(
|
|
|
|
|
p0_host_epoch_time: u128,
|
|
|
|
|
p1_host_uptime: u128,
|
|
|
|
|
p2a_host_setting_version_id: u32,
|
|
|
|
|
p2b_host_run_mode: HostRunMode,
|
|
|
|
|
p3_host_startup_counter: u64,
|
|
|
|
|
p5_host_name: Box<[u8]>,
|
|
|
|
|
p0_epoch_time: u128,
|
|
|
|
|
p1_uptime: u128,
|
|
|
|
|
p2_setting_version: u32,
|
|
|
|
|
p3_run_mode: HostRunMode,
|
|
|
|
|
p4_host_startup_counter: u64,
|
|
|
|
|
p5_host_name_length: u8,
|
|
|
|
|
p6_host_name_raw: [u8; 255],
|
|
|
|
|
) -> Self {
|
|
|
|
|
let _ = Self::_ENSURE;
|
|
|
|
|
let p4_host_name_length = p5_host_name.len();
|
|
|
|
|
let mut host_record_fl = [0u8; 56];
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P0..Self::HR_OFFSET_P1]
|
|
|
|
|
.copy_from_slice(&p0_host_epoch_time.to_le_bytes());
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P1..Self::HR_OFFSET_P2A]
|
|
|
|
|
.copy_from_slice(&p1_host_uptime.to_le_bytes());
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P2A..Self::HR_OFFSET_P2B]
|
|
|
|
|
.copy_from_slice(&p2a_host_setting_version_id.to_le_bytes());
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P2B..Self::HR_OFFSET_P3]
|
|
|
|
|
.copy_from_slice(&(p2b_host_run_mode.value_u8() as u32).to_le_bytes());
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P3..Self::HR_OFFSET_P4]
|
|
|
|
|
.copy_from_slice(&p3_host_startup_counter.to_le_bytes());
|
|
|
|
|
host_record_fl[Self::HR_OFFSET_P4..]
|
|
|
|
|
.copy_from_slice(&(p4_host_name_length as u64).to_le_bytes());
|
|
|
|
|
let mut data = [0u8; sizeof!(Self)];
|
|
|
|
|
data[Self::GRHR_OFFSET_P0..Self::GRHR_OFFSET_P1]
|
|
|
|
|
.copy_from_slice(&p0_epoch_time.to_le_bytes());
|
|
|
|
|
data[Self::GRHR_OFFSET_P1..Self::GRHR_OFFSET_P2].copy_from_slice(&p1_uptime.to_le_bytes());
|
|
|
|
|
data[Self::GRHR_OFFSET_P2..Self::GRHR_OFFSET_P3]
|
|
|
|
|
.copy_from_slice(&p2_setting_version.to_le_bytes());
|
|
|
|
|
data[Self::GRHR_OFFSET_P3..Self::GRHR_OFFSET_P4]
|
|
|
|
|
.copy_from_slice(&(p3_run_mode.value_u8() as u32).to_le_bytes());
|
|
|
|
|
data[Self::GRHR_OFFSET_P4..Self::GRHR_OFFSET_P5]
|
|
|
|
|
.copy_from_slice(&p4_host_startup_counter.to_le_bytes());
|
|
|
|
|
data[Self::GRHR_OFFSET_P5] = p5_host_name_length;
|
|
|
|
|
data[Self::GRHR_OFFSET_P6..].copy_from_slice(&p6_host_name_raw);
|
|
|
|
|
Self {
|
|
|
|
|
data: ByteStack::new(host_record_fl),
|
|
|
|
|
host_name: p5_host_name,
|
|
|
|
|
data: ByteStack::new(data),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub fn new_auto(
|
|
|
|
|
p2a_host_setting_version_id: u32,
|
|
|
|
|
p2b_host_run_mode: HostRunMode,
|
|
|
|
|
p3_host_startup_counter: u64,
|
|
|
|
|
p5_host_name: Box<[u8]>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let p0_host_epoch_time = crate::util::os::get_epoch_time();
|
|
|
|
|
let p1_host_uptime = crate::util::os::get_uptime();
|
|
|
|
|
Self::new(
|
|
|
|
|
p0_host_epoch_time,
|
|
|
|
|
p1_host_uptime,
|
|
|
|
|
p2a_host_setting_version_id,
|
|
|
|
|
p2b_host_run_mode,
|
|
|
|
|
p3_host_startup_counter,
|
|
|
|
|
p5_host_name,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HostRecordRaw {
|
|
|
|
|
pub const fn read_p0_epoch_time(&self) -> u128 {
|
|
|
|
|
self.data.read_xmmword(Self::HR_OFFSET_P0)
|
|
|
|
|
self.data.read_xmmword(Self::GRHR_OFFSET_P0)
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p1_uptime(&self) -> u128 {
|
|
|
|
|
self.data.read_xmmword(Self::HR_OFFSET_P1)
|
|
|
|
|
self.data.read_xmmword(Self::GRHR_OFFSET_P1)
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p2_setting_version_id(&self) -> u32 {
|
|
|
|
|
self.data.read_dword(Self::GRHR_OFFSET_P2)
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p3_run_mode(&self) -> HostRunMode {
|
|
|
|
|
HostRunMode::new_with_val(self.data.read_dword(Self::GRHR_OFFSET_P3))
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p2a_setting_version_id(&self) -> u32 {
|
|
|
|
|
self.data.read_dword(Self::HR_OFFSET_P2A)
|
|
|
|
|
pub const fn read_p4_startup_counter(&self) -> u64 {
|
|
|
|
|
self.data.read_qword(Self::GRHR_OFFSET_P4)
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p2b_run_mode(&self) -> HostRunMode {
|
|
|
|
|
HostRunMode::new_with_val(self.data.read_dword(Self::HR_OFFSET_P2B))
|
|
|
|
|
pub const fn read_p5_host_name_length(&self) -> usize {
|
|
|
|
|
self.data.read_byte(Self::GRHR_OFFSET_P5) as _
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p3_startup_counter(&self) -> u64 {
|
|
|
|
|
self.data.read_qword(Self::HR_OFFSET_P3)
|
|
|
|
|
pub fn read_p6_host_name_raw(&self) -> &[u8] {
|
|
|
|
|
&self.data.slice()[Self::GRHR_OFFSET_P6..]
|
|
|
|
|
}
|
|
|
|
|
pub const fn read_p4_host_name_length(&self) -> u64 {
|
|
|
|
|
self.data.read_qword(Self::HR_OFFSET_P4)
|
|
|
|
|
pub fn read_host_name(&self) -> &[u8] {
|
|
|
|
|
&self.data.slice()
|
|
|
|
|
[Self::GRHR_OFFSET_P6..Self::GRHR_OFFSET_P6 + self.read_p5_host_name_length()]
|
|
|
|
|
}
|
|
|
|
|
pub fn read_p5_host_name(&self) -> &[u8] {
|
|
|
|
|
&self.host_name
|
|
|
|
|
pub fn decoded(&self) -> GRHostRecord {
|
|
|
|
|
GRHostRecord::new(
|
|
|
|
|
self.read_p0_epoch_time(),
|
|
|
|
|
self.read_p1_uptime(),
|
|
|
|
|
self.read_p2_setting_version_id(),
|
|
|
|
|
self.read_p3_run_mode(),
|
|
|
|
|
self.read_p4_startup_counter(),
|
|
|
|
|
self.read_p5_host_name_length() as _,
|
|
|
|
|
util::copy_slice_to_array(self.read_p6_host_name_raw()),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_metadata_record_encode_decode() {
|
|
|
|
|
let md = MetadataRecordRaw::new(
|
|
|
|
|
let md = GRMetadataRecordRaw::new(
|
|
|
|
|
FileScope::TransactionLog,
|
|
|
|
|
FileSpecifier::GNSTxnLog,
|
|
|
|
|
FileSpecifierVersion(1),
|
|
|
|
@ -441,19 +410,20 @@ fn test_host_record_encode_decode() {
|
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.as_nanos();
|
|
|
|
|
let hr = HostRecordRaw::new(
|
|
|
|
|
let hr = GRHostRecordRaw::new(
|
|
|
|
|
time,
|
|
|
|
|
HOST_UPTIME,
|
|
|
|
|
HOST_SETTING_VERSION_ID,
|
|
|
|
|
HOST_RUN_MODE,
|
|
|
|
|
HOST_STARTUP_COUNTER,
|
|
|
|
|
HOST_NAME.as_bytes().to_owned().into_boxed_slice(),
|
|
|
|
|
HOST_NAME.len() as _,
|
|
|
|
|
crate::util::copy_str_to_array(HOST_NAME),
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(hr.read_p0_epoch_time(), time);
|
|
|
|
|
assert_eq!(hr.read_p1_uptime(), HOST_UPTIME);
|
|
|
|
|
assert_eq!(hr.read_p2a_setting_version_id(), HOST_SETTING_VERSION_ID);
|
|
|
|
|
assert_eq!(hr.read_p2b_run_mode(), HOST_RUN_MODE);
|
|
|
|
|
assert_eq!(hr.read_p3_startup_counter(), HOST_STARTUP_COUNTER);
|
|
|
|
|
assert_eq!(hr.read_p4_host_name_length(), HOST_NAME.len() as u64);
|
|
|
|
|
assert_eq!(hr.read_p5_host_name(), HOST_NAME.as_bytes());
|
|
|
|
|
assert_eq!(hr.read_p2_setting_version_id(), HOST_SETTING_VERSION_ID);
|
|
|
|
|
assert_eq!(hr.read_p3_run_mode(), HOST_RUN_MODE);
|
|
|
|
|
assert_eq!(hr.read_p4_startup_counter(), HOST_STARTUP_COUNTER);
|
|
|
|
|
assert_eq!(hr.read_p5_host_name_length(), HOST_NAME.len());
|
|
|
|
|
assert_eq!(hr.read_host_name(), HOST_NAME.as_bytes());
|
|
|
|
|
}
|
|
|
|
|