use jiminy_schema::indexer::{decode_account, matches_manifest, FieldValue};
use jiminy_schema::*;
fn order_book_manifest() -> LayoutManifest {
LayoutManifest {
name: "OrderBook",
version: 1,
discriminator: 5,
layout_id: [0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22, 0x33, 0x44],
fields: &[
FieldDescriptor {
name: "header",
canonical_type: CanonicalType::Header,
size: 16,
},
FieldDescriptor {
name: "market",
canonical_type: CanonicalType::Pubkey,
size: 32,
},
FieldDescriptor {
name: "counter",
canonical_type: CanonicalType::U64,
size: 8,
},
],
segments: &[
SegmentFieldDescriptor {
name: "bids",
element_type: "Order",
element_size: 16,
},
SegmentFieldDescriptor {
name: "asks",
element_type: "Order",
element_size: 16,
},
],
}
}
fn build_account_data(manifest: &LayoutManifest) -> Vec<u8> {
let total = 144; let mut data = vec![0u8; total];
data[0] = manifest.discriminator; data[1] = manifest.version; data[4..12].copy_from_slice(&manifest.layout_id);
data[16..48].copy_from_slice(&[0xDD; 32]);
data[48..56].copy_from_slice(&777u64.to_le_bytes());
data[56..60].copy_from_slice(&80u32.to_le_bytes());
data[60..62].copy_from_slice(&2u16.to_le_bytes());
data[62..64].copy_from_slice(&2u16.to_le_bytes());
data[64..66].copy_from_slice(&16u16.to_le_bytes());
data[66..68].copy_from_slice(&0u16.to_le_bytes());
data[68..72].copy_from_slice(&112u32.to_le_bytes());
data[72..74].copy_from_slice(&2u16.to_le_bytes());
data[74..76].copy_from_slice(&2u16.to_le_bytes());
data[76..78].copy_from_slice(&16u16.to_le_bytes());
data[78..80].copy_from_slice(&0u16.to_le_bytes());
data[80] = 0xBB;
data[96] = 0xB2;
data[112] = 0xAA;
data[128] = 0xA2;
data
}
#[test]
fn full_lifecycle_segmented_manifest() {
let manifest = order_book_manifest();
assert!(manifest.verify().is_ok(), "manifest verification failed");
assert_eq!(manifest.total_size(), 56); assert_eq!(manifest.min_size(), 80);
let json = manifest.export_json();
assert!(json.contains("\"name\": \"OrderBook\""));
assert!(json.contains("\"total_size\": 56"));
assert!(json.contains("\"min_size\": 80"));
assert!(json.contains("\"segments\":"));
assert!(json.contains("\"name\": \"bids\""));
assert!(json.contains("\"name\": \"asks\""));
assert!(json.contains("\"element_type\": \"Order\""));
assert!(json.contains("\"element_size\": 16"));
let data = build_account_data(&manifest);
assert_eq!(data.len(), 144);
assert!(
manifest.verify_account(&data).is_ok(),
"account verification failed"
);
assert!(matches_manifest(&manifest, &data));
let decoded = decode_account(&manifest, &data).unwrap();
assert_eq!(decoded.layout_name, "OrderBook");
assert_eq!(decoded.discriminator, 5);
assert_eq!(decoded.version, 1);
assert_eq!(decoded.fields.len(), 3);
assert_eq!(decoded.fields[0].name, "header");
assert_eq!(decoded.fields[1].name, "market");
if let FieldValue::Bytes(ref b) = decoded.fields[1].value {
assert_eq!(b, &[0xDD; 32]);
} else {
panic!("expected Bytes for market");
}
assert_eq!(decoded.fields[2].name, "counter");
assert_eq!(decoded.fields[2].value, FieldValue::U64(777));
assert_eq!(decoded.segments.len(), 2);
let bids = &decoded.segments[0];
assert_eq!(bids.name, "bids");
assert_eq!(bids.element_type, "Order");
assert_eq!(bids.count, 2);
assert_eq!(bids.capacity, 2);
assert_eq!(bids.element_size, 16);
assert_eq!(bids.flags, 0);
assert_eq!(bids.offset, 80);
assert_eq!(bids.data.len(), 32); assert_eq!(bids.data[0], 0xBB);
assert_eq!(bids.data[16], 0xB2);
let asks = &decoded.segments[1];
assert_eq!(asks.name, "asks");
assert_eq!(asks.count, 2);
assert_eq!(asks.capacity, 2);
assert_eq!(asks.data.len(), 32);
assert_eq!(asks.data[0], 0xAA);
assert_eq!(asks.data[16], 0xA2);
}
#[test]
fn hash_input_roundtrip() {
let manifest = order_book_manifest();
let input = manifest.hash_input();
assert!(input.starts_with("jiminy:v1:OrderBook:1:"));
assert!(input.contains("header:header:16,"));
assert!(input.contains("market:pubkey:32,"));
assert!(input.contains("counter:u64:8,"));
assert!(input.contains("seg:bids:Order:16,"));
assert!(input.contains("seg:asks:Order:16,"));
}
#[test]
fn verify_account_rejects_undersized_segmented() {
let manifest = order_book_manifest();
let mut data = vec![0u8; 60];
data[0] = manifest.discriminator;
data[4..12].copy_from_slice(&manifest.layout_id);
assert!(manifest.verify_account(&data).is_err());
}
#[test]
fn decode_rejects_undersized_segmented() {
let manifest = order_book_manifest();
let mut data = vec![0u8; 60];
data[0] = manifest.discriminator;
data[4..12].copy_from_slice(&manifest.layout_id);
assert!(decode_account(&manifest, &data).is_none());
}