use jbk::reader::builder::PropertyBuilderTrait;
use jbk::reader::Range;
use jubako as jbk;
use std::error::Error;
use std::fmt::Display;
#[derive(Debug)]
pub struct ExampleError(&'static str);
impl Display for ExampleError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for ExampleError {}
jbk::variants! {
VariantType {
Variant0 => "FirstVariant",
Variant1 => "SecondVariant"
}
}
jbk::properties! {
Property {
Value0:"array" => "AString",
Value1:"int" => "AInteger",
Variant0Value2:"content" => "TheContent",
Variant1Value2:"int" => "AnotherInteger"
}
}
pub struct Entry {
value0: jbk::SmallBytes,
value1: u64,
variant: Variant,
}
pub enum Variant {
Variant0 { value2: jbk::ContentAddress },
Variant1 { value2: u64 },
}
pub struct Builder {
store: jbk::reader::EntryStore,
variant_id: jbk::reader::builder::VariantIdBuilder<VariantType>,
value0: jbk::reader::builder::ArrayProperty,
value1: jbk::reader::builder::IntProperty,
variant0_value2: jbk::reader::builder::ContentProperty,
variant1_value2: jbk::reader::builder::IntProperty,
}
fn create_builder(
store: jbk::reader::EntryStore,
value_storage: &jbk::reader::ValueStorage,
) -> Result<Builder, Box<dyn Error>> {
let layout = store.layout();
assert_eq!(layout.variant_len(), 2);
let variant_id = layout.variant_id_builder().unwrap();
let value0 = jbk::layout_builder!(
layout[common][Property::Value0],
value_storage,
ExampleError
);
let value1 = jbk::layout_builder!(
layout[common][Property::Value1],
value_storage,
ExampleError
);
let variant0_value2 = jbk::layout_builder!(
layout[VariantType::Variant0][Property::Variant0Value2],
value_storage,
ExampleError
);
let variant1_value2 = jbk::layout_builder!(
layout[VariantType::Variant1][Property::Variant1Value2],
value_storage,
ExampleError
);
Ok(Builder {
store,
value0,
value1,
variant0_value2,
variant1_value2,
variant_id,
})
}
impl jbk::reader::builder::BuilderTrait for Builder {
type Entry = Entry;
type Error = jbk::Error;
fn create_entry(&self, idx: jbk::EntryIdx) -> jbk::Result<Option<Self::Entry>> {
let reader = self.store.get_entry_reader(idx);
if reader.is_none() {
return Ok(None);
}
let reader = reader.unwrap();
let mut value0 = jbk::SmallBytes::new();
self.value0.create(&reader)?.resolve_to_vec(&mut value0)?;
let value1 = self.value1.create(&reader)?;
match self.variant_id.create(&reader)? {
Some(VariantType::Variant0) => {
let value2 = self.variant0_value2.create(&reader)?;
Ok(Some(Entry {
value0,
value1,
variant: Variant::Variant0 { value2 },
}))
}
Some(VariantType::Variant1) => {
let value2 = self.variant1_value2.create(&reader)?;
Ok(Some(Entry {
value0,
value1,
variant: Variant::Variant1 { value2 },
}))
}
None => Ok(None),
}
}
}
fn main() -> Result<(), Box<dyn Error>> {
let container = jbk::reader::Container::new("test.jbkm")?; let index = container
.get_index_for_name("My own index")?
.expect("'My own index' is in the container.");
let builder = create_builder(
index.get_store(container.get_entry_storage())?,
container.get_value_storage(),
)?;
{
let entry = index
.get_entry(&builder, 0.into())?
.expect("Entry 0 exists in the index");
assert_eq!(entry.value0, b"Super");
assert_eq!(entry.value1, 50);
if let Variant::Variant0 { value2 } = entry.variant {
let reader = container
.get_bytes(value2)?
.and_then(|m| m.transpose())
.expect("value2 should be valid")
.unwrap();
std::io::copy(&mut reader.stream(), &mut std::io::stdout().lock())?;
} else {
panic!("We should have variant0")
}
}
{
let entry = index
.get_entry(&builder, 1.into())?
.expect("Entry 1 exists in the index");
assert_eq!(entry.value0, b"Mega");
assert_eq!(entry.value1, 42);
if let Variant::Variant1 { value2 } = entry.variant {
assert_eq!(value2, 5);
} else {
panic!("We should have variant1")
}
}
{
let entry = index
.get_entry(&builder, 2.into())?
.expect("Entry 2 exists in the index");
assert_eq!(entry.value0, b"Hyper");
assert_eq!(entry.value1, 45);
if let Variant::Variant1 { value2 } = entry.variant {
assert_eq!(value2, 2);
} else {
panic!("We should have variant1")
}
}
Ok(())
}