pub struct AuditEntry { /* private fields */ }Expand description
Audit trail entry with hash chain integrity
Fixed 80-byte structure as specified in RFC-0002 Section 5.4.
All integers are little-endian. Layout is #[repr(C)] for deterministic serialization.
§Memory Layout
Offset Size Field
------ ---- -----
0 8 timestamp
8 8 author_id
16 2 action_code
18 6 reserved1
24 8 details_offset
32 4 details_length
36 4 reserved2
40 32 previous_hash
72 8 reserved3
------ ----
Total: 80 bytes§Examples
use aion_context::audit::{AuditEntry, ActionCode};
use aion_context::types::AuthorId;
let entry = AuditEntry::new(
1_700_000_000_000_000_000,
AuthorId(1001),
ActionCode::CommitVersion,
100,
27,
[0u8; 32],
);
// Verify size
assert_eq!(std::mem::size_of_val(&entry), 80);
// Access fields
assert_eq!(entry.action_code().unwrap(), ActionCode::CommitVersion);
assert_eq!(entry.author_id(), AuthorId(1001));Implementations§
Source§impl AuditEntry
impl AuditEntry
Sourcepub const fn new(
timestamp: u64,
author_id: AuthorId,
action_code: ActionCode,
details_offset: u64,
details_length: u32,
previous_hash: [u8; 32],
) -> Self
pub const fn new( timestamp: u64, author_id: AuthorId, action_code: ActionCode, details_offset: u64, details_length: u32, previous_hash: [u8; 32], ) -> Self
Create a new audit entry
§Arguments
timestamp- Nanoseconds since Unix epoch (useSystemTime::now())author_id- Author performing the actionaction_code- Type of operation (seeActionCode)details_offset- Byte offset in string tabledetails_length- Length of details string (excluding null)previous_hash- BLAKE3 hash of previous entry (all zeros for genesis)
§Examples
use aion_context::audit::{AuditEntry, ActionCode};
use aion_context::types::AuthorId;
let entry = AuditEntry::new(
1_700_000_000_000_000_000,
AuthorId(1001),
ActionCode::Verify,
200,
42,
[0xAB; 32],
);Get the author ID
Sourcepub const fn action_code(&self) -> Result<ActionCode>
pub const fn action_code(&self) -> Result<ActionCode>
Sourcepub const fn action_code_raw(&self) -> u16
pub const fn action_code_raw(&self) -> u16
Get the action code as raw u16 (no validation)
Sourcepub const fn details_offset(&self) -> u64
pub const fn details_offset(&self) -> u64
Get the details offset in string table
Sourcepub const fn details_length(&self) -> u32
pub const fn details_length(&self) -> u32
Get the details string length (bytes, excluding null terminator)
Sourcepub const fn previous_hash(&self) -> &[u8; 32]
pub const fn previous_hash(&self) -> &[u8; 32]
Get the previous entry hash
Sourcepub fn is_genesis(&self) -> bool
pub fn is_genesis(&self) -> bool
Check if this is a genesis entry (first in chain)
Genesis entries have an all-zero previous hash.
Sourcepub fn compute_hash(&self) -> [u8; 32]
pub fn compute_hash(&self) -> [u8; 32]
Compute BLAKE3 hash of this entry
The hash includes all 80 bytes of the entry. This hash becomes the
previous_hash value for the next entry in the chain.
§Examples
use aion_context::audit::{AuditEntry, ActionCode};
use aion_context::types::AuthorId;
let entry = AuditEntry::new(
1_700_000_000_000_000_000,
AuthorId(1001),
ActionCode::CreateGenesis,
0,
10,
[0u8; 32],
);
let entry_hash = entry.compute_hash();
assert_eq!(entry_hash.len(), 32);Sourcepub const fn as_bytes(&self) -> &[u8] ⓘ
pub const fn as_bytes(&self) -> &[u8] ⓘ
Serialize entry to bytes (little-endian)
Returns exactly 80 bytes in RFC-0002 specified format.
§Safety
This function is safe because:
AuditEntryhas#[repr(C)]for deterministic layout- All fields are plain-old-data (POD) types
- The lifetime of the returned slice is tied to
self - The size is compile-time verified to be 80 bytes
Sourcepub fn from_bytes(bytes: &[u8]) -> Result<Self>
pub fn from_bytes(bytes: &[u8]) -> Result<Self>
Deserialize entry from bytes
§Errors
Returns an error if the input is not exactly 80 bytes.
§Safety
This function is safe because:
- Length is validated to be exactly 80 bytes
AuditEntryis#[repr(C)]with POD fields- All bit patterns are valid for the field types
- No references or complex types that need initialization
Note: Callers should validate field values (e.g., action_code) after deserialization.
Sourcepub fn validate_chain(&self, previous_entry: &Self) -> Result<()>
pub fn validate_chain(&self, previous_entry: &Self) -> Result<()>
Validate this entry against the previous entry
Checks that:
- The
previous_hashmatches the hash ofprevious_entry - The timestamp is not before the previous entry
- Reserved fields are zero
§Errors
Returns an error if validation fails.
§Examples
use aion_context::audit::{AuditEntry, ActionCode};
use aion_context::types::AuthorId;
let genesis = AuditEntry::new(
1_700_000_000_000_000_000,
AuthorId(1001),
ActionCode::CreateGenesis,
0,
10,
[0u8; 32],
);
let genesis_hash = genesis.compute_hash();
let entry2 = AuditEntry::new(
1_700_000_001_000_000_000,
AuthorId(1002),
ActionCode::CommitVersion,
10,
15,
genesis_hash,
);
assert!(entry2.validate_chain(&genesis).is_ok());Trait Implementations§
Source§impl Clone for AuditEntry
impl Clone for AuditEntry
Source§fn clone(&self) -> AuditEntry
fn clone(&self) -> AuditEntry
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AuditEntry
impl Debug for AuditEntry
Source§impl PartialEq for AuditEntry
impl PartialEq for AuditEntry
impl Copy for AuditEntry
impl Eq for AuditEntry
impl StructuralPartialEq for AuditEntry
Auto Trait Implementations§
impl Freeze for AuditEntry
impl RefUnwindSafe for AuditEntry
impl Send for AuditEntry
impl Sync for AuditEntry
impl Unpin for AuditEntry
impl UnsafeUnpin for AuditEntry
impl UnwindSafe for AuditEntry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more