use alloc::string::String;
use core::{convert::Into, default::Default, option::Option, time::Duration};
use serde::{Deserialize, Serialize};
use crate::{
bolts::serdeany::SerdeAnyMap,
inputs::{HasLen, Input},
state::HasMetadata,
Error,
};
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct Testcase<I>
where
I: Input,
{
input: Option<I>,
filename: Option<String>,
metadata: SerdeAnyMap,
exec_time: Option<Duration>,
cached_len: Option<usize>,
}
impl<I> HasMetadata for Testcase<I>
where
I: Input,
{
#[inline]
fn metadata(&self) -> &SerdeAnyMap {
&self.metadata
}
#[inline]
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl<I> Testcase<I>
where
I: Input,
{
pub fn load_input(&mut self) -> Result<&I, Error> {
if self.input.is_none() {
self.input = Some(I::from_file(self.filename.as_ref().unwrap())?);
}
Ok(self.input.as_ref().unwrap())
}
pub fn store_input(&mut self) -> Result<bool, Error> {
let fname;
match self.filename() {
Some(f) => {
fname = f.clone();
}
None => {
return Ok(false);
}
};
match self.input_mut() {
None => Ok(false),
Some(i) => {
i.to_file(fname)?;
Ok(true)
}
}
}
#[inline]
pub fn input(&self) -> &Option<I> {
&self.input
}
#[inline]
pub fn input_mut(&mut self) -> &mut Option<I> {
&mut self.input
}
#[inline]
pub fn set_input(&mut self, input: I) {
self.input = Some(input);
}
#[inline]
pub fn filename(&self) -> &Option<String> {
&self.filename
}
#[inline]
pub fn filename_mut(&mut self) -> &mut Option<String> {
&mut self.filename
}
#[inline]
pub fn set_filename(&mut self, filename: String) {
self.filename = Some(filename);
}
pub fn exec_time(&self) -> &Option<Duration> {
&self.exec_time
}
pub fn exec_time_mut(&mut self) -> &mut Option<Duration> {
&mut self.exec_time
}
#[inline]
pub fn new<T>(input: T) -> Self
where
T: Into<I>,
{
Testcase {
input: Some(input.into()),
filename: None,
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
#[inline]
pub fn with_filename(input: I, filename: String) -> Self {
Testcase {
input: Some(input),
filename: Some(filename),
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
#[must_use]
#[inline]
pub fn default() -> Self {
Testcase {
input: None,
filename: None,
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
}
impl<I> Testcase<I>
where
I: Input + HasLen,
{
#[inline]
pub fn cached_len(&mut self) -> Result<usize, Error> {
Ok(match &self.input {
Some(i) => {
let l = i.len();
self.cached_len = Some(l);
l
}
None => {
if let Some(l) = self.cached_len {
l
} else {
let l = self.load_input()?.len();
self.cached_len = Some(l);
l
}
}
})
}
}
impl<I> From<I> for Testcase<I>
where
I: Input,
{
fn from(input: I) -> Self {
Testcase::new(input)
}
}