dochy_diff 0.10.1

Calculates Dochy Diff.
use crate::imp::read::reader::Reader;
use dochy_core::structs::{MetaTable, MetaValue, VarType, Qv, MetaParam};
use crate::diff_error::{DiffError, OptToErr};
use crate::imp::read::read_store_ids::read_stored_ids;
use crate::imp::write::store_ids::StoredIDs;

pub(crate) fn read_refs(r : &mut Reader, meta : &MetaTable,
                 ss : &mut Vec<(usize, Qv<String>)>) -> Result<(), DiffError> {
    let ids = read_stored_ids(r)?;
    match ids{
        StoredIDs::Zero => return Ok(()),
        StoredIDs::U64(b) =>{
            read_refs_bits(r, b, meta, 0, ss)?;
            Ok(())
        },
        StoredIDs::Bits(b) => {
            let mut offset = 0;
            for &bits in &b{
                read_refs_bits(r, bits, meta, offset, ss)?;
                offset += 64;
            }
            Ok(())
        },
        StoredIDs::Numbers(n) => {
            for idx in n {
                let p = if let Some((_, MetaValue::Param(p))) = meta.get(idx) { p } else {
                    panic!("invalid meta read_a_ref")
                };
                if let Some(p) = read_a_ref(r, p)? {
                    ss.push((idx,p));
                }
            }
            Ok(())
        }
    }
}

pub(crate) fn read_refs_bits(reader : &mut Reader, bits : u64, meta : &MetaTable, offset : usize, r : &mut Vec<(usize, Qv<String>)>) -> Result<(), DiffError> {
    let mut flag: u64 = 1;
    let mut index = 0;

    for _ in 0..64 {
        if bits & flag != 0 {
            let p = if let Some((_, MetaValue::Param(p))) = meta.get(index + offset) { p } else {
                panic!("invalid meta read_a_ref")
            };
            if let Some(p) = read_a_ref(reader, p)? {
                r.push((index + offset, p))
            }
        }
        flag <<= 1;
        index += 1;
        if bits < flag { break }
    }
    return Ok(())
}


fn read_a_ref(r : &mut Reader, p : &MetaParam) -> Result<Option<Qv<String>>, DiffError> {
    match p.var_type() {
        VarType::Normal => {
            Ok(Some(read_val(r)?))
        },
        VarType::Nullable => {
            if r.read()?.ast_bool()? {
                Ok(Some(read_val(r)?))
            } else {
                Ok(Some(Qv::Null))
            }
        },
        VarType::Undefiable => {
            if r.read()?.ast_bool()? {
                Ok(Some(read_val(r)?))
            } else {
                Ok(Some(Qv::Undefined))
            }
        },
        VarType::UndefNullable => {
            if r.read()?.ast_bool()? {
                Ok(Some(read_val(r)?))
            } else if r.read()?.ast_bool()? {
                Ok(Some(Qv::Null))
            } else {
                Ok(Some(Qv::Undefined))
            }
        }
    }
}

fn read_val(r : &mut Reader) -> Result<Qv<String>, DiffError>{
    Ok(Qv::Val(r.read()?.ast_string()?))
}