persy_expimp 1.1.0

Export and Import data from Persy single file transactional persistence engine
Documentation
use crate::{export, export_from_snapshot, import, EIRes, Info};
use bincode::{deserialize_from, serialize};
use persy::{Persy, Snapshot};
use std::io::{Read, Write};

pub fn import_binary(persy: &Persy, read: &mut dyn Read) -> EIRes<()> {
    import(persy, Reader { read })
}

pub fn export_binary(persy: &Persy, write: &mut dyn Write) -> EIRes<()> {
    for info in export(persy)? {
        write.write_all(&serialize(&true)?)?;
        write.write_all(&serialize(&info)?)?;
    }
    write.write_all(&serialize(&false)?)?;
    Ok(())
}

pub fn export_binary_from_snapshot(snapshot: &Snapshot, write: &mut dyn Write) -> EIRes<()> {
    for info in export_from_snapshot(snapshot)? {
        write.write_all(&serialize(&true)?)?;
        write.write_all(&serialize(&info)?)?;
    }
    write.write_all(&serialize(&false)?)?;
    Ok(())
}

struct Reader<'a> {
    read: &'a mut dyn Read,
}
impl<'a> Iterator for Reader<'a> {
    type Item = Info;

    fn next(&mut self) -> Option<Self::Item> {
        if let Ok(more) = deserialize_from(&mut self.read) {
            if more {
                if let Ok(info) = deserialize_from(&mut self.read) {
                    Some(info)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{export_binary, import_binary};
    use persy::{ByteVec, IndexType, OpenOptions, Persy, PersyId, Transaction, ValueMode};
    use std::io::Cursor;

    fn util<C, V>(create: C, verify: V)
    where
        C: FnOnce(&mut Transaction),
        V: FnOnce(&Persy),
    {
        let p = OpenOptions::new().memory().expect("open fine");
        let mut tx = p.begin().unwrap();
        create(&mut tx);
        let prep = tx.prepare().unwrap();
        prep.commit().unwrap();
        let mut data = Vec::new();
        export_binary(&p, &mut data).unwrap();
        let p1 = OpenOptions::new().memory().expect("open fine");
        import_binary(&p1, &mut Cursor::new(data)).unwrap();
        verify(&p1);
    }

    fn check_key_value<K: IndexType + PartialEq, V: IndexType + PartialEq + std::fmt::Debug>(
        p: &Persy,
        index: &str,
        k: K,
        v: V,
    ) {
        assert_eq!(v, p.get::<K, V>(index, &k).unwrap().into_iter().next().unwrap());
    }

    #[test]
    fn binary_all_data_export_import() {
        util(
            |tx| {
                tx.create_segment("test").unwrap();
                let persy_id = tx.insert("test", &"test".to_string().as_bytes()).unwrap();
                tx.create_index::<u8, u8>("test_u8", ValueMode::Replace).unwrap();
                tx.put::<u8, u8>("test_u8", 10, 10).unwrap();
                tx.create_index::<u16, u16>("test_u16", ValueMode::Replace).unwrap();
                tx.put::<u16, u16>("test_u16", 10, 10).unwrap();
                tx.create_index::<u32, u32>("test_u32", ValueMode::Replace).unwrap();
                tx.put::<u32, u32>("test_u32", 10, 10).unwrap();
                tx.create_index::<u64, u64>("test_u64", ValueMode::Replace).unwrap();
                tx.put::<u64, u64>("test_u64", 10, 10).unwrap();
                tx.create_index::<u128, u128>("test_u128", ValueMode::Replace).unwrap();
                tx.put::<u128, u128>("test_u128", 10, 10).unwrap();
                tx.create_index::<i8, i8>("test_i8", ValueMode::Replace).unwrap();
                tx.put::<i8, i8>("test_i8", 10, 10).unwrap();
                tx.create_index::<i16, i16>("test_i16", ValueMode::Replace).unwrap();
                tx.put::<i16, i16>("test_i16", 10, 10).unwrap();
                tx.create_index::<i32, i32>("test_i32", ValueMode::Replace).unwrap();
                tx.put::<i32, i32>("test_i32", 10, 10).unwrap();
                tx.create_index::<i64, i64>("test_i64", ValueMode::Replace).unwrap();
                tx.put::<i64, i64>("test_i64", 10, 10).unwrap();
                tx.create_index::<i128, i128>("test_i128", ValueMode::Replace).unwrap();
                tx.put::<i128, i128>("test_i128", 10, 10).unwrap();
                tx.create_index::<f32, f32>("test_f32", ValueMode::Replace).unwrap();
                tx.put::<f32, f32>("test_f32", 10.0, 10.0).unwrap();
                tx.create_index::<f64, f64>("test_f64", ValueMode::Replace).unwrap();
                tx.put::<f64, f64>("test_f64", 10.0, 10.0).unwrap();
                tx.create_index::<String, String>("test_string", ValueMode::Replace)
                    .unwrap();
                tx.put::<String, String>("test_string", "one".to_string(), "two".to_string())
                    .unwrap();
                tx.create_index::<ByteVec, ByteVec>("test_bytevec", ValueMode::Replace)
                    .unwrap();
                let bv = ByteVec::new(vec![20, 10]);
                let bv1 = ByteVec::new(vec![10, 20]);
                tx.put::<ByteVec, ByteVec>("test_bytevec", bv, bv1).unwrap();
                tx.create_index::<PersyId, PersyId>("test_p", ValueMode::Replace)
                    .unwrap();
                tx.put::<PersyId, PersyId>("test_p", persy_id.clone(), persy_id)
                    .unwrap();
            },
            |p| {
                for (_, content) in p.scan("test").unwrap() {
                    assert_eq!("test".to_string().as_bytes().to_vec(), content);
                }
                check_key_value(p, "test_u8", 10 as u8, 10 as u8);
                check_key_value(p, "test_u16", 10 as u16, 10 as u16);
                check_key_value(p, "test_u32", 10 as u32, 10 as u32);
                check_key_value(p, "test_u64", 10 as u64, 10 as u64);
                check_key_value(p, "test_u128", 10 as u128, 10 as u128);
                check_key_value(p, "test_i8", 10 as i8, 10 as i8);
                check_key_value(p, "test_i16", 10 as i16, 10 as i16);
                check_key_value(p, "test_i32", 10 as i32, 10 as i32);
                check_key_value(p, "test_i64", 10 as i64, 10 as i64);
                check_key_value(p, "test_i128", 10 as i128, 10 as i128);
                check_key_value(p, "test_f32", 10 as f32, 10 as f32);
                check_key_value(p, "test_f64", 10 as f64, 10 as f64);
                check_key_value(p, "test_string", "one".to_string(), "two".to_string());
                let bv = ByteVec::new(vec![20, 10]);
                let bv1 = ByteVec::new(vec![10, 20]);
                check_key_value(p, "test_bytevec", bv, bv1);
                assert_eq!(
                    1,
                    p.range::<PersyId, PersyId, _>("test_p", ..)
                        .unwrap()
                        .into_iter()
                        .count()
                );
            },
        );
    }
}