1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#![feature(
    specialization,
    integer_atomics,
    box_syntax,
)]

#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate kg_display_derive;
#[macro_use]
extern crate kg_diag_derive;


use kg_symbol::Symbol;
use kg_diag::*;
use kg_io::{MemCharReader, CharReader};
use kg_utils::collections::LinkedHashMap;

mod tree;

pub use tree::{NodeRef, ErrorKind};
pub use tree::metadata::{FileInfo, FileFormat};
pub use tree::node::{Kind, KindMask, Value, Node};
pub use tree::convert::Primitive;
pub use kg_io::FileType;

use tree::metadata::Metadata;

use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::cell::RefCell;
use std::collections::HashMap;

use heapsize::HeapSizeOf;

pub type Properties = LinkedHashMap<Symbol, NodeRef>;
pub type Elements = Vec<NodeRef>;

pub mod opath;
pub mod diff;

pub mod serial;


thread_local! {
    static BASE_PATH: RefCell<PathBuf> = RefCell::new(std::env::current_dir().unwrap());
    static BASE_PATH_STACK: RefCell<Vec<PathBuf>> = RefCell::new(Vec::new());
}

pub fn set_base_path<P: AsRef<Path> + Into<PathBuf>>(base_path: P) {
    debug_assert!(base_path.as_ref().is_absolute());
    BASE_PATH_STACK.with(|s| s.borrow_mut().clear());
    BASE_PATH.with(|b| b.replace(base_path.into()));
}

pub fn push_base_path<P: AsRef<Path> + Into<PathBuf>>(base_path: P) {
    debug_assert!(base_path.as_ref().is_absolute());
    let current_path = BASE_PATH.with(|b| b.replace(base_path.into()));
    BASE_PATH_STACK.with(|s| s.borrow_mut().push(current_path));
}

pub fn pop_base_path() -> PathBuf {
    let path = BASE_PATH_STACK.with(|s| s.borrow_mut().pop().expect("kg_tree::pop_base_path() called on an empty stack"));
    BASE_PATH.with(|b| b.replace(path))
}

pub fn relative_path(path: &Path) -> &Path {
    debug_assert!(path.is_absolute());
    BASE_PATH.with(|b| {
        unsafe { std::mem::transmute(path.strip_prefix(b.borrow().as_path()).unwrap_or(path)) }
    })
}

pub fn resolve_path(path: &Path) -> Cow<Path> {
    if path.is_absolute() {
        path.into()
    } else {
        BASE_PATH.with(|b| b.borrow().as_path().join(path).into())
    }
}

pub fn resolve_path_str(path: &str) -> Cow<Path> {
    resolve_path(Path::new(path))
}


struct PathBufHeapSize<'a>(&'a PathBuf);

impl<'a> HeapSizeOf for PathBufHeapSize<'a> {
    fn heap_size_of_children(&self) -> usize {
        unsafe { std::mem::transmute::<&PathBuf, &Vec<u8>>(self.0).heap_size_of_children() }
    }
}


pub type NodeMap = HashMap<*const Node, NodeRef>;

pub trait Remappable {
    fn remap(&mut self, node_map: &NodeMap);
}