Redefine SDSS Header records to have fixed layout

next
Sayan Nandan 1 year ago
parent e126c826f9
commit 45c93eac3c
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -24,13 +24,16 @@
*
*/
use crate::engine::{
mem::ByteStack,
storage::{
header::{HostArch, HostEndian, HostOS, HostPointerWidth},
v1::header_impl::FileSpecifierVersion,
versions::{DriverVersion, ServerVersion},
use crate::{
engine::{
mem::ByteStack,
storage::{
header::{HostArch, HostEndian, HostOS, HostPointerWidth},
v1::header_impl::FileSpecifierVersion,
versions::{DriverVersion, ServerVersion},
},
},
util,
};
/*
@ -56,6 +59,39 @@ pub struct DRHostSignature {
os: HostOS,
}
impl DRHostSignature {
/// Decode the [`DRHostSignature`] from the given bytes
///
/// **☢ WARNING ☢: This only decodes; it doesn't validate expected values!**
pub fn decode(bytes: [u8; sizeof!(DRHostSignatureRaw)]) -> Option<Self> {
let ns = ByteStack::new(bytes);
let server_version = ServerVersion::__new(u64::from_le(
ns.read_qword(DRHostSignatureRaw::DRHS_OFFSET_P0),
));
let driver_version = DriverVersion::__new(u64::from_le(
ns.read_qword(DRHostSignatureRaw::DRHS_OFFSET_P1),
));
let file_specifier_id = FileSpecifierVersion::__new(u32::from_le(
ns.read_dword(DRHostSignatureRaw::DRHS_OFFSET_P2),
));
let endian =
HostEndian::try_new_with_val(ns.read_byte(DRHostSignatureRaw::DRHS_OFFSET_P3))?;
let ptr_width =
HostPointerWidth::try_new_with_val(ns.read_byte(DRHostSignatureRaw::DRHS_OFFSET_P4))?;
let arch = HostArch::try_new_with_val(ns.read_byte(DRHostSignatureRaw::DRHS_OFFSET_P5))?;
let os = HostOS::try_new_with_val(ns.read_byte(DRHostSignatureRaw::DRHS_OFFSET_P6))?;
Some(Self::new(
server_version,
driver_version,
file_specifier_id,
endian,
ptr_width,
arch,
os,
))
}
}
impl DRHostSignature {
pub const fn new(
server_version: ServerVersion,
@ -191,7 +227,7 @@ impl DRHostSignatureRaw {
pub const fn read_p6_os(&self) -> HostOS {
HostOS::new_with_val(self.data.read_byte(Self::DRHS_OFFSET_P6))
}
pub const fn encoded(&self) -> DRHostSignature {
pub const fn decoded(&self) -> DRHostSignature {
DRHostSignature::new(
self.read_p0_server_version(),
self.read_p1_driver_version(),
@ -210,99 +246,60 @@ impl DRHostSignatureRaw {
- 8B: Dynamic record modify count
- 16B: Host epoch time
- 16B: Host uptime
- 8B: Host name length
- ?B: Host name
- 1B: Host name length
- 255B: Host name (nulled)
= 296B
*/
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq)]
pub struct DRRuntimeSignature {
rt_signature_fixed: DRRuntimeSignatureFixed,
host_name: Box<[u8]>,
modify_count: u64,
epoch_time: u128,
host_uptime: u128,
host_name_length: u8,
host_name_raw: [u8; 255],
}
impl DRRuntimeSignature {
pub fn new(fixed: DRRuntimeSignatureFixed, host_name: Box<[u8]>) -> Self {
Self {
rt_signature_fixed: fixed,
host_name,
}
}
pub const fn rt_signature_fixed(&self) -> &DRRuntimeSignatureFixed {
&self.rt_signature_fixed
}
pub fn host_name(&self) -> &[u8] {
self.host_name.as_ref()
}
pub fn into_encoded(self) -> DRRuntimeSignatureRaw {
let len = self.host_name.len();
DRRuntimeSignatureRaw::new_with_sections(
self.host_name,
self.rt_signature_fixed.encoded(len),
)
}
pub fn encoded(&self) -> DRRuntimeSignatureRaw {
self.clone().into_encoded()
}
}
pub struct DRRuntimeSignatureRaw {
rt_signature: DRRuntimeSignatureFixedRaw,
pub(super) host_name: Box<[u8]>,
}
impl DRRuntimeSignatureRaw {
pub fn new(host_name: Box<[u8]>, modify_count: u64) -> Self {
Self {
rt_signature: DRRuntimeSignatureFixedRaw::new(modify_count, host_name.len()),
host_name,
}
}
pub fn new_with_sections(host_name: Box<[u8]>, fixed: DRRuntimeSignatureFixedRaw) -> Self {
Self {
rt_signature: fixed,
host_name,
}
}
pub fn decode(
data: [u8; sizeof!(DRRuntimeSignatureFixedRaw)],
) -> Option<(usize, DRRuntimeSignatureFixed)> {
let s = ByteStack::new(data);
let modify_count = u64::from_le(s.read_qword(DRRuntimeSignatureFixedRaw::DRRS_OFFSET_P0));
let epoch_time = u128::from_le(s.read_xmmword(DRRuntimeSignatureFixedRaw::DRRS_OFFSET_P1));
let uptime = u128::from_le(s.read_xmmword(DRRuntimeSignatureFixedRaw::DRRS_OFFSET_P2));
let host_name_length =
u64::from_le(s.read_qword(DRRuntimeSignatureFixedRaw::DRRS_OFFSET_P3));
if epoch_time > crate::util::os::get_epoch_time() || host_name_length > usize::MAX as u64 {
// damn, this file is from the future; I WISH EVERYONE HAD NTP SYNC GRRRR
// or, we have a bad host name. like, what?
return None;
pub fn decode(bytes: [u8; sizeof!(DRRuntimeSignatureRaw)]) -> Option<Self> {
let bytes = ByteStack::new(bytes);
// check
let modify_count = u64::from_le(bytes.read_qword(DRRuntimeSignatureRaw::DRRS_OFFSET_P0));
let epoch_time = u128::from_le(bytes.read_xmmword(DRRuntimeSignatureRaw::DRRS_OFFSET_P1));
let host_uptime = u128::from_le(bytes.read_xmmword(DRRuntimeSignatureRaw::DRRS_OFFSET_P2));
let host_name_length = bytes.read_byte(DRRuntimeSignatureRaw::DRRS_OFFSET_P3);
let host_name_raw =
util::copy_slice_to_array(&bytes.slice()[DRRuntimeSignatureRaw::DRRS_OFFSET_P4..]);
if cfg!(debug_assertions) {
assert_eq!(
255 - host_name_raw.iter().filter(|b| **b == 0u8).count(),
host_name_length as _
);
}
Some((
host_name_length as _,
DRRuntimeSignatureFixed::new(modify_count, epoch_time, uptime),
))
}
pub const fn runtime_signature(&self) -> &DRRuntimeSignatureFixedRaw {
&self.rt_signature
}
pub fn name(&self) -> &[u8] {
&self.host_name
Some(Self {
modify_count,
epoch_time,
host_uptime,
host_name_length,
host_name_raw,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct DRRuntimeSignatureFixed {
modify_count: u64,
epoch_time: u128,
uptime: u128,
}
impl DRRuntimeSignatureFixed {
pub const fn new(modify_count: u64, epoch_time: u128, uptime: u128) -> Self {
impl DRRuntimeSignature {
pub const fn new(
modify_count: u64,
epoch_time: u128,
host_uptime: u128,
host_name_length: u8,
host_name_raw: [u8; 255],
) -> Self {
Self {
modify_count,
epoch_time,
uptime,
host_uptime,
host_name_length,
host_name_raw,
}
}
pub const fn modify_count(&self) -> u64 {
@ -311,51 +308,69 @@ impl DRRuntimeSignatureFixed {
pub const fn epoch_time(&self) -> u128 {
self.epoch_time
}
pub const fn uptime(&self) -> u128 {
self.uptime
pub const fn host_uptime(&self) -> u128 {
self.host_uptime
}
pub const fn host_name_length(&self) -> u8 {
self.host_name_length
}
pub fn encoded(&self, host_name_length: usize) -> DRRuntimeSignatureFixedRaw {
DRRuntimeSignatureFixedRaw::new_full(
pub const fn host_name_raw(&self) -> [u8; 255] {
self.host_name_raw
}
pub fn host_name(&self) -> &[u8] {
&self.host_name_raw[..self.host_name_length() as usize]
}
pub fn encoded(&self) -> DRRuntimeSignatureRaw {
DRRuntimeSignatureRaw::new(
self.modify_count(),
self.epoch_time(),
self.uptime(),
host_name_length,
self.host_uptime(),
self.host_name_length(),
self.host_name_raw(),
)
}
}
pub struct DRRuntimeSignatureFixedRaw {
data: ByteStack<48>,
#[derive(Debug, PartialEq, Clone)]
pub struct DRRuntimeSignatureRaw {
data: ByteStack<296>,
}
impl DRRuntimeSignatureFixedRaw {
impl DRRuntimeSignatureRaw {
const DRRS_OFFSET_P0: usize = 0;
const DRRS_OFFSET_P1: usize = sizeof!(u64);
const DRRS_OFFSET_P2: usize = Self::DRRS_OFFSET_P1 + sizeof!(u128);
const DRRS_OFFSET_P3: usize = Self::DRRS_OFFSET_P2 + sizeof!(u128);
const _ENSURE: () = assert!(Self::DRRS_OFFSET_P3 == sizeof!(Self) - 8);
pub fn new_full(
const DRRS_OFFSET_P4: usize = Self::DRRS_OFFSET_P3 + 1;
const _ENSURE: () = assert!(Self::DRRS_OFFSET_P4 == sizeof!(Self) - 255);
pub fn new(
modify_count: u64,
epoch_time: u128,
uptime: u128,
host_name_length: usize,
host_epoch_time: u128,
host_uptime: u128,
host_name_length: u8,
host_name: [u8; 255],
) -> Self {
let _ = Self::_ENSURE;
let mut data = [0u8; sizeof!(Self)];
data[0..8].copy_from_slice(&modify_count.to_le_bytes());
data[8..24].copy_from_slice(&epoch_time.to_le_bytes());
data[24..40].copy_from_slice(&uptime.to_le_bytes());
data[40..48].copy_from_slice(&(host_name_length as u64).to_le_bytes());
let mut data = [0u8; 296];
data[Self::DRRS_OFFSET_P0..Self::DRRS_OFFSET_P1]
.copy_from_slice(&modify_count.to_le_bytes());
data[Self::DRRS_OFFSET_P1..Self::DRRS_OFFSET_P2]
.copy_from_slice(&host_epoch_time.to_le_bytes());
data[Self::DRRS_OFFSET_P2..Self::DRRS_OFFSET_P3]
.copy_from_slice(&host_uptime.to_le_bytes());
data[Self::DRRS_OFFSET_P3] = host_name_length;
data[Self::DRRS_OFFSET_P4..].copy_from_slice(&host_name);
Self {
data: ByteStack::new(data),
}
}
pub fn new(modify_count: u64, host_name_length: usize) -> Self {
Self::new_full(
modify_count,
crate::util::os::get_epoch_time(),
crate::util::os::get_uptime(),
host_name_length,
pub fn decoded(&self) -> DRRuntimeSignature {
DRRuntimeSignature::new(
self.read_p0_modify_count(),
self.read_p1_epoch_time(),
self.read_p2_uptime(),
self.read_p3_host_name_length() as _,
util::copy_slice_to_array(self.read_p4_host_name_raw_null()),
)
}
pub const fn read_p0_modify_count(&self) -> u64 {
@ -367,7 +382,45 @@ impl DRRuntimeSignatureFixedRaw {
pub const fn read_p2_uptime(&self) -> u128 {
self.data.read_xmmword(Self::DRRS_OFFSET_P2)
}
pub const fn read_p3_host_name_length(&self) -> u64 {
self.data.read_qword(Self::DRRS_OFFSET_P3)
pub const fn read_p3_host_name_length(&self) -> usize {
self.data.read_byte(Self::DRRS_OFFSET_P3) as _
}
pub fn read_p4_host_name_raw_null(&self) -> &[u8] {
&self.data.slice()[Self::DRRS_OFFSET_P4..]
}
pub fn read_host_name(&self) -> &[u8] {
&self.data.slice()
[Self::DRRS_OFFSET_P4..Self::DRRS_OFFSET_P4 + self.read_p3_host_name_length()]
}
}
#[test]
fn test_dr_host_signature_encode_decode() {
const TARGET: DRHostSignature = DRHostSignature::new(
crate::engine::storage::versions::v1::V1_SERVER_VERSION,
crate::engine::storage::versions::v1::V1_DRIVER_VERSION,
FileSpecifierVersion::__new(u32::MAX - 3),
HostEndian::new(),
HostPointerWidth::new(),
HostArch::new(),
HostOS::new(),
);
let encoded = TARGET.encoded();
let decoded = encoded.decoded();
assert_eq!(decoded, TARGET);
}
#[test]
fn test_dr_runtime_signature_encoded_decode() {
const TARGET: DRRuntimeSignature = DRRuntimeSignature::new(
u64::MAX - 3,
u128::MAX - u32::MAX as u128,
u128::MAX - u32::MAX as u128,
"skycloud".len() as _,
util::copy_str_to_array("skycloud"),
);
let encoded = TARGET.encoded();
let decoded = encoded.decoded();
assert_eq!(decoded, TARGET);
assert_eq!(decoded.host_name(), b"skycloud");
}

@ -24,12 +24,15 @@
*
*/
use crate::engine::{
mem::ByteStack,
storage::{
v1::header_impl::{FileScope, FileSpecifier, FileSpecifierVersion, HostRunMode},
versions::{self, DriverVersion, ServerVersion},
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_p2a_setting_version_id(&self) -> u32 {
self.data.read_dword(Self::HR_OFFSET_P2A)
pub const fn read_p2_setting_version_id(&self) -> u32 {
self.data.read_dword(Self::GRHR_OFFSET_P2)
}
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_p3_run_mode(&self) -> HostRunMode {
HostRunMode::new_with_val(self.data.read_dword(Self::GRHR_OFFSET_P3))
}
pub const fn read_p3_startup_counter(&self) -> u64 {
self.data.read_qword(Self::HR_OFFSET_P3)
pub const fn read_p4_startup_counter(&self) -> u64 {
self.data.read_qword(Self::GRHR_OFFSET_P4)
}
pub const fn read_p4_host_name_length(&self) -> u64 {
self.data.read_qword(Self::HR_OFFSET_P4)
pub const fn read_p5_host_name_length(&self) -> usize {
self.data.read_byte(Self::GRHR_OFFSET_P5) as _
}
pub fn read_p5_host_name(&self) -> &[u8] {
&self.host_name
pub fn read_p6_host_name_raw(&self) -> &[u8] {
&self.data.slice()[Self::GRHR_OFFSET_P6..]
}
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 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());
}

@ -63,8 +63,6 @@ mod gr;
// (3) dr
mod dr;
use crate::engine::mem::ByteStack;
/// The file scope
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, sky_macros::EnumMethods)]
@ -146,8 +144,8 @@ pub struct SDSSHeader {
// static record
sr: sr::StaticRecord,
// genesis record
gr_mdr: gr::MetadataRecord,
gr_hr: gr::HostRecord,
gr_mdr: gr::GRMetadataRecord,
gr_hr: gr::GRHostRecord,
// dynamic record
dr_hs: dr::DRHostSignature,
dr_rs: dr::DRRuntimeSignature,
@ -156,8 +154,8 @@ pub struct SDSSHeader {
impl SDSSHeader {
pub const fn new(
sr: sr::StaticRecord,
gr_mdr: gr::MetadataRecord,
gr_hr: gr::HostRecord,
gr_mdr: gr::GRMetadataRecord,
gr_hr: gr::GRHostRecord,
dr_hs: dr::DRHostSignature,
dr_rs: dr::DRRuntimeSignature,
) -> Self {
@ -169,22 +167,13 @@ impl SDSSHeader {
dr_rs,
}
}
pub fn encode(&self) -> SDSSHeaderRaw {
SDSSHeaderRaw::new_full(
self.sr.encode(),
self.gr_mdr.encode(),
self.gr_hr.encode(),
self.dr_hs().encoded(),
self.dr_rs().encoded(),
)
}
pub fn sr(&self) -> &sr::StaticRecord {
&self.sr
}
pub fn gr_mdr(&self) -> &gr::MetadataRecord {
pub fn gr_mdr(&self) -> &gr::GRMetadataRecord {
&self.gr_mdr
}
pub fn gr_hr(&self) -> &gr::HostRecord {
pub fn gr_hr(&self) -> &gr::GRHostRecord {
&self.gr_hr
}
pub fn dr_hs(&self) -> &dr::DRHostSignature {
@ -193,12 +182,21 @@ impl SDSSHeader {
pub fn dr_rs(&self) -> &dr::DRRuntimeSignature {
&self.dr_rs
}
pub fn encode(&self) -> SDSSHeaderRaw {
SDSSHeaderRaw::new_full(
self.sr.encode(),
self.gr_mdr().encoded(),
self.gr_hr().encoded(),
self.dr_hs().encoded(),
self.dr_rs().encoded(),
)
}
}
pub struct SDSSHeaderRaw {
sr: sr::StaticRecordRaw,
gr_0_mdr: gr::MetadataRecordRaw,
gr_1_hr: gr::HostRecordRaw,
gr_0_mdr: gr::GRMetadataRecordRaw,
gr_1_hr: gr::GRHostRecordRaw,
dr_0_hs: dr::DRHostSignatureRaw,
dr_1_rs: dr::DRRuntimeSignatureRaw,
}
@ -206,8 +204,8 @@ pub struct SDSSHeaderRaw {
impl SDSSHeaderRaw {
pub fn new_full(
sr: sr::StaticRecordRaw,
gr_mdr: gr::MetadataRecordRaw,
gr_hr: gr::HostRecordRaw,
gr_mdr: gr::GRMetadataRecordRaw,
gr_hr: gr::GRHostRecordRaw,
dr_hs: dr::DRHostSignatureRaw,
dr_rs: dr::DRRuntimeSignatureRaw,
) -> Self {
@ -221,22 +219,17 @@ impl SDSSHeaderRaw {
}
pub fn new(
sr: sr::StaticRecordRaw,
gr_0_mdr: gr::MetadataRecordRaw,
gr_1_hr_const_section: gr::HRConstSectionRaw,
gr_1_hr_host_name: Box<[u8]>,
gr_0_mdr: gr::GRMetadataRecordRaw,
gr_1_hr: gr::GRHostRecordRaw,
dr_hs: dr::DRHostSignatureRaw,
dr_rs_const: dr::DRRuntimeSignatureFixedRaw,
dr_rs_host_name: Box<[u8]>,
dr_rs: dr::DRRuntimeSignatureRaw,
) -> Self {
Self {
sr,
gr_0_mdr,
gr_1_hr: gr::HostRecordRaw {
data: ByteStack::new(gr_1_hr_const_section),
host_name: gr_1_hr_host_name,
},
gr_1_hr,
dr_0_hs: dr_hs,
dr_1_rs: dr::DRRuntimeSignatureRaw::new_with_sections(dr_rs_host_name, dr_rs_const),
dr_1_rs: dr_rs,
}
}
pub fn get0_sr(&self) -> &[u8] {
@ -248,19 +241,11 @@ impl SDSSHeaderRaw {
pub fn get1_dr_1_hr_0(&self) -> &[u8] {
self.gr_1_hr.data.slice()
}
pub fn get1_dr_1_hr_1(&self) -> &[u8] {
self.gr_1_hr.host_name.as_ref()
}
pub fn calculate_header_size(&self) -> usize {
Self::calculate_fixed_header_size()
+ self.gr_1_hr.host_name.len()
+ self.dr_1_rs.host_name.len()
}
pub const fn calculate_fixed_header_size() -> usize {
sizeof!(sr::StaticRecordRaw)
+ sizeof!(gr::MetadataRecordRaw)
+ sizeof!(gr::HRConstSectionRaw)
+ sizeof!(gr::GRMetadataRecordRaw)
+ sizeof!(gr::GRHostRecordRaw)
+ sizeof!(dr::DRHostSignatureRaw)
+ sizeof!(dr::DRRuntimeSignatureFixedRaw)
+ sizeof!(dr::DRRuntimeSignatureRaw)
}
}

@ -62,7 +62,7 @@ impl StaticRecordRaw {
pub const fn empty_buffer() -> [u8; sizeof!(Self)] {
[0u8; sizeof!(Self)]
}
pub fn decode_from_bytes(buf: [u8; sizeof!(Self)]) -> Option<StaticRecord> {
pub fn decode(buf: [u8; sizeof!(Self)]) -> Option<StaticRecord> {
StaticRecordUVRaw::decode_from_bytes(buf).map(StaticRecord::new)
}
}

@ -362,3 +362,17 @@ macro_rules! byte_repr_impls {
}
byte_repr_impls!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
pub const fn copy_slice_to_array<const N: usize>(bytes: &[u8]) -> [u8; N] {
assert!(bytes.len() <= N);
let mut data = [0u8; N];
let mut i = 0;
while i < bytes.len() {
data[i] = bytes[i];
i += 1;
}
data
}
pub const fn copy_str_to_array<const N: usize>(str: &str) -> [u8; N] {
copy_slice_to_array(str.as_bytes())
}

Loading…
Cancel
Save