hooo 0.10.0

Propositional logic with exponentials
Documentation
use crate::*;

use piston_meta::{Range, MetaData};
use std::sync::{Arc, Mutex};
use serde::{Serialize, Deserialize};

#[derive(Hash, PartialEq, Eq)]
pub struct Key {
    pub source: Arc<String>,
    pub syntax: Arc<String>,
}

pub struct MetaCache {
    pub cache: Arc<Mutex<HashMap<Key, Result<Vec<Range<MetaData>>, String>>>>,
}

impl MetaCache {
    pub fn new() -> MetaCache {
        MetaCache {
            cache: Arc::new(HashMap::default().into()),
        }
    }

    pub fn is_empty(&self) -> bool {
        let guard = self.cache.lock().unwrap();
        (&*guard).is_empty()
    }

    pub fn len(&self) -> usize {
        let guard = self.cache.lock().unwrap();
        (&*guard).values().count()
    }

    pub fn get(&self, key: &Key) -> Option<Result<Vec<Range<MetaData>>, String>> {
        let guard = match self.cache.lock() {
            Ok(x) => x,
            Err(_) => panic!("Could not lock mutex in meta cache"),
        };
        guard.get(key).map(|n| n.clone())
    }

    pub fn insert(&self, key: Key, data: Result<Vec<Range<MetaData>>, String>) {
        let mut guard = match self.cache.lock() {
            Ok(x) => x,
            Err(_) => panic!("Could not lock mutex in meta cache"),
        };
        guard.insert(key, data);
    }

    pub fn store(self, file: &str) -> Result<(), String> {
        use std::fs::File;
        use deflate::write::DeflateEncoder;
        use deflate::Compression;

        let store: MetaStore = self.into();
        let mut w = DeflateEncoder::new(File::create(file)
            .map_err(|_| format!("Could not write to `{}`", file))?, Compression::Default);
        bincode::serialize_into(&mut w, &store)
            .map_err(|_| format!("Serialization to file `{}` failed", file))
    }

    pub fn restore(file: &str) -> MetaCache {
        use std::fs::File;
        use inflate::DeflateDecoder;

        let file = match File::open(file) {
            Ok(x) => x,
            Err(_) => return MetaCache::new(),
        };
        let r = DeflateDecoder::new(file);
        let store: MetaStore = match bincode::deserialize_from(r) {
            Ok(x) => x,
            Err(_) => return MetaCache::new(),
        };
        store.into()
    }
}

#[derive(Serialize, Deserialize)]
pub struct MetaStore {
    pub strings: Vec<String>,
    pub data: Vec<((u32, u32), Result<Vec<(u32, u32, MetaDataStore)>, u32>)>,
}

impl From<MetaStore> for MetaCache {
    fn from(store: MetaStore) -> MetaCache {
        let MetaStore {data, strings} = store;

        let mut map = HashMap::default();
        let strings: Vec<Arc<String>> = strings.into_iter().map(|n| Arc::new(n)).collect();
        for (key, val) in data.into_iter() {
            let val = match val {
                Ok(val) => Ok(val.into_iter().map(|n| Range::new(n.0 as usize, n.1 as usize)
                    .wrap(n.2.to(&strings))).collect()),
                Err(err) => Err((*strings[err as usize]).clone())
            };
            map.insert(Key {source: strings[key.0 as usize].clone(),
                            syntax: strings[key.1 as usize].clone()}, val);
        }
        MetaCache {
            cache: Arc::new(map.into()),
        }
    }
}

impl From<MetaCache> for MetaStore {
    fn from(cache: MetaCache) -> MetaStore {
        let mut data = vec![];
        let cache = cache.cache.lock().unwrap();
        let mut strings = vec![];
        let mut strings_cache: HashMap<String, u32> = HashMap::default();
        for (key, val) in cache.iter() {
            let val = match val {
                Ok(val) => Ok(val.iter().map(|n| {
                    (n.offset as u32,
                     n.length as u32,
                     MetaDataStore::from(n.data.clone(), &mut strings, &mut strings_cache))
                }).collect()),
                Err(err) => Err(id(&**err, &mut strings, &mut strings_cache)),
            };
            let source = id(&**key.source, &mut strings, &mut strings_cache);
            let syntax = id(&**key.syntax, &mut strings, &mut strings_cache);
            data.push(((source, syntax), val));
        }
        MetaStore {
            strings,
            data,
        }
    }
}

fn id(s: &str, strings: &mut Vec<String>, strings_cache: &mut HashMap<String, u32>) -> u32 {
    if let Some(id) = strings_cache.get(s) {
        *id
    } else {
        let id = strings.len();
        strings.push(s.into());
        strings_cache.insert(s.into(), id as u32);
        id as u32
    }
}

#[derive(Serialize, Deserialize)]
pub enum MetaDataStore {
    StartNode(u32),
    EndNode(u32),
    Bool(u32, bool),
    F64(u32, f64),
    String(u32, u32),
}

impl MetaDataStore {
    pub fn to(self, strings: &[Arc<String>]) -> MetaData {
        match self {
            MetaDataStore::StartNode(n) => MetaData::StartNode(strings[n as usize].clone()),
            MetaDataStore::EndNode(n) => MetaData::EndNode(strings[n as usize].clone()),
            MetaDataStore::Bool(n, v) => MetaData::Bool(strings[n as usize].clone(), v),
            MetaDataStore::F64(n, v) => MetaData::F64(strings[n as usize].clone(), v),
            MetaDataStore::String(n, v) => MetaData::String(strings[n as usize].clone(),
                                                            strings[v as usize].clone()),
        }
    }

    pub fn from(
        val: MetaData,
        strings: &mut Vec<String>,
        strings_cache: &mut HashMap<String, u32>
    ) -> MetaDataStore {
        match val {
            MetaData::StartNode(n) => MetaDataStore::StartNode(id(&**n, strings, strings_cache)),
            MetaData::EndNode(n) => MetaDataStore::EndNode(id(&**n, strings, strings_cache)),
            MetaData::Bool(n, v) => MetaDataStore::Bool(id(&**n, strings, strings_cache), v),
            MetaData::F64(n, v) => MetaDataStore::F64(id(&**n, strings, strings_cache), v),
            MetaData::String(n, v) => MetaDataStore::String(id(&**n, strings, strings_cache),
                                                            id(&**v, strings, strings_cache)),
        }
    }
}