use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::rc::Rc;
pub type PathSet = HashSet<String>;
#[derive(Debug, Copy, Clone)]
pub enum Change {
Added,
Deleted,
Modified,
Renamed{ percent_changed: u8},
Copied{ percent_changed: u8},
}
#[derive(Debug, Clone)]
pub struct FileDelta {
pub change: Change,
pub path: String,
pub from: String,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct SHA1 {
bytes: [u8; 20]
}
#[derive(Copy, Clone, Debug)]
pub enum SHA1ParseError {
IncorrectLength,
InvalidHexadecimal
}
impl Error for SHA1ParseError {
fn description(&self) -> &str {
match *self {
SHA1ParseError::IncorrectLength => "String is not 40 characters long",
SHA1ParseError::InvalidHexadecimal => "String is not valid hexadecimal",
}
}
}
impl Display for SHA1ParseError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl SHA1 {
pub fn parse(s: &str) -> Result<SHA1, SHA1ParseError> {
if s.len() != 40 { return Err(SHA1ParseError::IncorrectLength) }
let mut ret = SHA1::default();
for i in 0..20 {
let char_index = i * 2;
ret.bytes[i] = match u8::from_str_radix(&s[char_index .. char_index + 2], 16) {
Ok(b) => b,
_ => { return Err(SHA1ParseError::InvalidHexadecimal); },
};
}
Ok(ret)
}
}
impl Display for SHA1 {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
for b in &self.bytes {
match write!(f, "{:02x}", b) {
Ok (()) => { },
err => { return err; }
};
}
Ok(())
}
}
impl Default for SHA1 {
fn default() -> SHA1 { SHA1{bytes: [0; 20]} }
}
pub type Link<T> = Rc<RefCell<T>>;
pub struct HistoryNode<T> {
pub data: Option<Rc<T>>,
pub previous: Option<Link<HistoryNode<T>>>,
}
pub type HistoryTree<T> = HashMap<String, Link<HistoryNode<T>>>;