#![cfg_attr(docsrs, feature(doc_cfg))]
use gatesim::*;
pub use toml;
use serde::de::{DeserializeOwned, Error};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::str::FromStr;
#[derive(thiserror::Error, Debug)]
pub enum ValidError {
#[error("Invalid state length")]
InvalidStateLength,
#[error("Invalid data part length")]
InvalidDataPartLength,
#[error("Invalid cell length bits")]
InvalidCellLenBits,
#[error("Invalid processor's number")]
InvalidProcNum,
#[error("Invalid max temp buffer length")]
InvalidMaxTempBufferLength,
#[error("Invalid circuit input length")]
InvalidCircuitInputLength,
#[error("Invalid circuit output length")]
InvalidCircuitOutputLength,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct InfParMachineConfig {
pub state_len: u32,
pub data_part_len: u32,
pub cell_len_bits: u32,
}
impl InfParMachineConfig {
pub fn valid(&self) -> Result<(), ValidError> {
if self.state_len == 0 {
return Err(ValidError::InvalidStateLength);
}
if self.data_part_len == 0 {
return Err(ValidError::InvalidDataPartLength);
}
if self.cell_len_bits >= 64 {
return Err(ValidError::InvalidCellLenBits);
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct InfParInterfaceConfig {
pub data_part_len: u32,
pub cell_len_bits: u32,
}
impl InfParInterfaceConfig {
pub fn valid(&self) -> Result<(), ValidError> {
if self.data_part_len == 0 {
return Err(ValidError::InvalidDataPartLength);
}
if self.cell_len_bits >= 64 {
return Err(ValidError::InvalidCellLenBits);
}
Ok(())
}
}
impl From<(InfParInterfaceConfig, u32)> for InfParMachineConfig {
fn from((c, s): (InfParInterfaceConfig, u32)) -> Self {
Self {
state_len: s,
data_part_len: c.data_part_len,
cell_len_bits: c.cell_len_bits,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct InfParEnvConfig {
pub proc_num: u64,
pub flat_memory: bool,
pub max_temp_buffer_len: u32,
pub max_mem_size: Option<u64>,
}
impl InfParEnvConfig {
pub fn valid(&self) -> Result<(), ValidError> {
if self.proc_num == 0 || self.proc_num < 1024 {
return Err(ValidError::InvalidProcNum);
}
if self.max_temp_buffer_len == 0 {
return Err(ValidError::InvalidMaxTempBufferLength);
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct InfParMachineData<T>
where
T: Clone + Copy + FromStr + Debug + Default + PartialOrd + Ord + std::ops::Add<Output = T>,
T: From<u8>,
usize: TryFrom<T>,
<usize as TryFrom<T>>::Error: Debug,
T: TryFrom<usize>,
<T as TryFrom<usize>>::Error: Debug,
<T as FromStr>::Err: Debug,
{
pub config: InfParMachineConfig,
pub env_config: InfParEnvConfig,
pub circuit: Circuit<T>,
}
impl<T> InfParMachineData<T>
where
T: Clone + Copy + FromStr + Debug + Default + PartialOrd + Ord + std::ops::Add<Output = T>,
T: From<u8> + Serialize + DeserializeOwned,
usize: TryFrom<T>,
<usize as TryFrom<T>>::Error: Debug,
T: TryFrom<usize>,
<T as TryFrom<usize>>::Error: Debug,
<T as FromStr>::Err: Debug,
{
pub fn valid(&self) -> Result<(), ValidError> {
self.config.valid()?;
self.env_config.valid()?;
let circuit_input_len = usize::try_from(self.circuit.input_len()).unwrap();
let state_len = circuit_input_len
- (1 << self.config.cell_len_bits)
- self.config.data_part_len as usize
- 1;
if state_len != self.config.state_len as usize {
return Err(ValidError::InvalidCircuitInputLength);
}
if self.circuit.outputs().len() != circuit_input_len + 8 {
return Err(ValidError::InvalidCircuitOutputLength);
}
Ok(())
}
pub fn to_toml(&self) -> Result<String, toml::ser::Error> {
toml::to_string_pretty(self)
}
pub fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
let d: Self = toml::from_str(s)?;
if let Err(e) = d.valid() {
return Err::<Self, _>(toml::de::Error::custom(e.to_string()));
}
Ok(d)
}
}
pub type InfParMachineData16 = InfParMachineData<u16>;
pub type InfParMachineData32 = InfParMachineData<u32>;
pub type InfParMachineDataSys = InfParMachineData<usize>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize() {
let config = InfParMachineConfig {
state_len: 44,
data_part_len: 32,
cell_len_bits: 5,
};
let env_config = InfParEnvConfig {
proc_num: 64 * 1024,
flat_memory: true,
max_temp_buffer_len: 96,
max_mem_size: Some(400 * 1024),
};
assert_eq!(
r##"state_len = 44
data_part_len = 32
cell_len_bits = 5
"##,
toml::to_string_pretty(&config).unwrap()
);
assert_eq!(
r##"proc_num = 65536
flat_memory = true
max_temp_buffer_len = 96
max_mem_size = 409600
"##,
toml::to_string_pretty(&env_config).unwrap()
);
let machine_data = InfParMachineData {
config,
env_config,
circuit: Circuit::<u32>::new(2, [Gate::new_and(0, 1)], [(2, false)]).unwrap(),
};
assert_eq!(
r##"circuit = """
{
0
1
and(0,1):0
}(2)
"""
[config]
state_len = 44
data_part_len = 32
cell_len_bits = 5
[env_config]
proc_num = 65536
flat_memory = true
max_temp_buffer_len = 96
max_mem_size = 409600
"##,
machine_data.to_toml().unwrap()
);
}
#[test]
fn test_deserialize() {
let config = InfParMachineConfig {
state_len: 44,
data_part_len: 32,
cell_len_bits: 5,
};
let env_config = InfParEnvConfig {
proc_num: 64 * 1024,
flat_memory: true,
max_temp_buffer_len: 96,
max_mem_size: Some(400 * 1024),
};
let mem_cell_data_part_len = (1 << config.cell_len_bits) + config.data_part_len;
let circuit_input_len = config.state_len + mem_cell_data_part_len + 1;
assert_eq!(
InfParMachineData {
config,
env_config,
circuit: Circuit::<u32>::new(
circuit_input_len,
[Gate::new_nor(0, circuit_input_len - 1)],
std::iter::once((circuit_input_len, true)).chain(
(1..circuit_input_len - 1)
.chain(0..9)
.map(|i| (i, i >= config.state_len && i < circuit_input_len - 1)),
),
)
.unwrap(),
},
InfParMachineData::<u32>::from_toml(
r##"circuit = """{
0:108
1:1:109
2:2:110
3:3:111
4:4:112
5:5:113
6:6:114
7:7:115
8:8:116
9:9
10:10
11:11
12:12
13:13
14:14
15:15
16:16
17:17
18:18
19:19
20:20
21:21
22:22
23:23
24:24
25:25
26:26
27:27
28:28
29:29
30:30
31:31
32:32
33:33
34:34
35:35
36:36
37:37
38:38
39:39
40:40
41:41
42:42
43:43
44:44n
45:45n
46:46n
47:47n
48:48n
49:49n
50:50n
51:51n
52:52n
53:53n
54:54n
55:55n
56:56n
57:57n
58:58n
59:59n
60:60n
61:61n
62:62n
63:63n
64:64n
65:65n
66:66n
67:67n
68:68n
69:69n
70:70n
71:71n
72:72n
73:73n
74:74n
75:75n
76:76n
77:77n
78:78n
79:79n
80:80n
81:81n
82:82n
83:83n
84:84n
85:85n
86:86n
87:87n
88:88n
89:89n
90:90n
91:91n
92:92n
93:93n
94:94n
95:95n
96:96n
97:97n
98:98n
99:99n
100:100n
101:101n
102:102n
103:103n
104:104n
105:105n
106:106n
107:107n
108
nor(0,108):0n
}(109)
"""
[config]
state_len = 44
data_part_len = 32
cell_len_bits = 5
[env_config]
proc_num = 65536
flat_memory = true
max_temp_buffer_len = 96
max_mem_size = 409600
"##
)
.unwrap()
)
}
}