#![cfg_attr(not(all(target_os = "linux", target_arch = "x86_64")), allow(dead_code))]
use std::sync::{Arc, RwLock};
use zisk_asm_runner::HintsShmem;
use zisk_common::io::StreamSource;
use zisk_precomp_hints::HintsProcessor;
use crate::error::{ExecutorError, ExecutorResult, RwLockExt};
use crate::AsmResources;
pub struct AsmTransport {
asm_resources: RwLock<Option<Arc<AsmResources>>>,
}
impl AsmTransport {
pub fn new() -> Self {
Self { asm_resources: RwLock::new(None) }
}
pub fn set_asm_resources(&self, asm_resources: Arc<AsmResources>) -> ExecutorResult<()> {
*self.asm_resources.write_or_poison("asm_resources")? = Some(asm_resources);
Ok(())
}
pub fn resources(&self) -> ExecutorResult<Arc<AsmResources>> {
self.asm_resources
.read_or_poison("asm_resources")?
.as_ref()
.ok_or(ExecutorError::AsmResourcesNotInitialized)
.cloned()
}
pub fn signal_cancellation(&self) -> ExecutorResult<()> {
match self.installed_resources_ref()? {
Some(r) => r.signal_cancellation(),
None => Ok(()),
}
}
pub fn get_hints_processor(&self) -> ExecutorResult<Arc<HintsProcessor<HintsShmem>>> {
self.resources()?.get_hints_processor()
}
pub fn set_active_services(&self, is_first_process: bool) -> ExecutorResult<()> {
match self.installed_resources_ref()? {
Some(r) => r.set_active_services(is_first_process),
None => Ok(()),
}
}
pub fn set_hints_stream_src(&self, stream: StreamSource) -> ExecutorResult<()> {
self.resources()?.set_hints_stream_src(stream)
}
pub fn set_inputs_stream_src(&self, stream: StreamSource) -> ExecutorResult<()> {
self.resources()?.set_inputs_stream_src(stream)
}
pub fn submit_hint_direct(&self, data: &[u64]) -> ExecutorResult<()> {
self.resources()?.submit_hint_direct(data)
}
pub fn append_raw_input(&self, bytes: &[u8]) -> ExecutorResult<()> {
self.resources()?.append_raw_input(bytes)
}
pub fn reset(&self) -> ExecutorResult<()> {
if let Some(r) = self.installed_resources_ref()? {
r.reset();
}
Ok(())
}
fn installed_resources_ref(&self) -> ExecutorResult<Option<Arc<AsmResources>>> {
Ok(self.asm_resources.read_or_poison("asm_resources")?.as_ref().cloned())
}
}
impl Default for AsmTransport {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resources_errs_before_install() {
let t = AsmTransport::new();
let err = t.resources().expect_err("must err when uninstalled");
assert!(err.to_string().contains("AsmResources not initialized"));
}
#[test]
fn get_hints_processor_errs_before_install() {
let t = AsmTransport::new();
match t.get_hints_processor() {
Ok(_) => panic!("must err when uninstalled"),
Err(err) => assert!(err.to_string().contains("AsmResources not initialized")),
}
}
#[test]
fn signal_cancellation_silent_when_uninstalled() {
let t = AsmTransport::new();
t.signal_cancellation().expect("must be a silent no-op");
}
#[test]
fn reset_silent_when_uninstalled() {
let t = AsmTransport::new();
t.reset().expect("must be a silent no-op");
}
#[test]
fn set_active_services_silent_when_uninstalled() {
let t = AsmTransport::new();
t.set_active_services(true).expect("must be a silent no-op");
}
#[test]
fn submit_hint_direct_errs_before_install() {
let t = AsmTransport::new();
let err = t.submit_hint_direct(&[]).expect_err("must err");
assert!(err.to_string().contains("AsmResources not initialized"));
}
#[test]
fn append_raw_input_errs_before_install() {
let t = AsmTransport::new();
let err = t.append_raw_input(&[]).expect_err("must err");
assert!(err.to_string().contains("AsmResources not initialized"));
}
}