use serde::{Deserialize, Serialize};
#[cfg(feature = "reader")]
pub mod fp_utils;
#[cfg(feature = "reader")]
pub mod tier0;
#[cfg(feature = "reader")]
pub mod tier1;
#[cfg(feature = "reader")]
pub mod tier2;
pub const PIR_DEPTH: usize = 25;
pub const TIER0_LAYERS: usize = 9;
pub const TIER1_LAYERS: usize = 6;
pub const TIER2_LAYERS: usize = 10;
pub const TIER1_ROWS: usize = 1 << TIER0_LAYERS;
pub const TIER2_ROWS: usize = 1 << (TIER0_LAYERS + TIER1_LAYERS);
pub const TIER1_LEAVES: usize = 1 << TIER1_LAYERS;
pub const TIER2_LEAVES: usize = 1 << TIER2_LAYERS;
pub const YPIR_MIN_ROWS: usize = 2048;
pub const TIER1_YPIR_ROWS: usize = if TIER1_ROWS >= YPIR_MIN_ROWS { TIER1_ROWS } else { YPIR_MIN_ROWS };
pub const TIER2_LEAF_BYTES: usize = 96;
pub const TIER1_ROW_BYTES: usize = TIER1_LEAVES * 64;
pub const TIER2_ROW_BYTES: usize = TIER2_LEAVES * TIER2_LEAF_BYTES;
pub const TIER1_ITEM_BITS: usize = TIER1_ROW_BYTES * 8;
pub const TIER2_ITEM_BITS: usize = TIER2_ROW_BYTES * 8;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PirMetadata {
pub root25: String,
pub root29: String,
pub num_ranges: usize,
pub pir_depth: usize,
pub tier0_bytes: usize,
pub tier1_rows: usize,
pub tier1_row_bytes: usize,
pub tier2_rows: usize,
pub tier2_row_bytes: usize,
pub height: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YpirScenario {
pub num_items: usize,
pub item_size_bits: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RootInfo {
pub root29: String,
pub root25: String,
pub num_ranges: usize,
pub pir_depth: usize,
pub height: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthInfo {
pub status: String,
pub tier1_rows: usize,
pub tier2_rows: usize,
pub tier1_row_bytes: usize,
pub tier2_row_bytes: usize,
}
const U64_BYTES: usize = std::mem::size_of::<u64>();
pub fn serialize_ypir_query(pqr: &[u64], pub_params: &[u64]) -> Vec<u8> {
let pqr_byte_len = pqr.len() * U64_BYTES;
let mut payload = Vec::with_capacity(U64_BYTES + (pqr.len() + pub_params.len()) * U64_BYTES);
payload.extend_from_slice(&(pqr_byte_len as u64).to_le_bytes());
for &v in pqr {
payload.extend_from_slice(&v.to_le_bytes());
}
for &v in pub_params {
payload.extend_from_slice(&v.to_le_bytes());
}
payload
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_ypir_query_empty() {
let result = serialize_ypir_query(&[], &[]);
assert_eq!(result.len(), U64_BYTES);
assert_eq!(u64::from_le_bytes(result[..8].try_into().unwrap()), 0);
}
#[test]
fn serialize_ypir_query_round_trip_layout() {
let pqr = vec![1u64, 2, 3];
let pp = vec![100u64, 200];
let payload = serialize_ypir_query(&pqr, &pp);
let expected_len = U64_BYTES + (pqr.len() + pp.len()) * U64_BYTES;
assert_eq!(payload.len(), expected_len);
let pqr_byte_len = u64::from_le_bytes(payload[..8].try_into().unwrap()) as usize;
assert_eq!(pqr_byte_len, pqr.len() * U64_BYTES);
for (i, &expected) in pqr.iter().enumerate() {
let offset = U64_BYTES + i * U64_BYTES;
let val = u64::from_le_bytes(payload[offset..offset + U64_BYTES].try_into().unwrap());
assert_eq!(val, expected);
}
for (i, &expected) in pp.iter().enumerate() {
let offset = U64_BYTES + pqr_byte_len + i * U64_BYTES;
let val = u64::from_le_bytes(payload[offset..offset + U64_BYTES].try_into().unwrap());
assert_eq!(val, expected);
}
}
#[test]
fn serialize_ypir_query_length_prefix_correctness() {
let pqr = vec![42u64];
let pp = vec![99u64];
let payload = serialize_ypir_query(&pqr, &pp);
let pqr_byte_len = u64::from_le_bytes(payload[..8].try_into().unwrap()) as usize;
assert_eq!(pqr_byte_len, 8);
let remaining = payload.len() - U64_BYTES - pqr_byte_len;
assert_eq!(remaining, pp.len() * U64_BYTES);
}
}