use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };
use self::Value::*;
use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);
impl<T> Lazy<T>
where T: Copy {
#[inline]
pub fn get(&self) -> Option<T> { self.0.get() }
#[inline]
pub fn get_or_else<F>(&self, f: F) -> T
where F: FnOnce() -> T {
if let Some(value) = self.0.get() {
value
} else {
let value = f();
self.0.set(Some(value));
value
}
}
#[inline]
pub fn new() -> Self {
Lazy(Cell::new(None))
}
}
impl<T> Default for Lazy<T>
where T: Copy {
fn default() -> Self {
Self::new()
}
}
impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
, T: Copy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0.get() { Some(value) => value.fmt(f)
, None => write!(f, "?")
}
}
}
macro_rules! lazy_field {
($method: ident, $field: ident, $ty:ty) => {
#[inline] fn $method(&self) -> $ty {
self.$field.get_or_else(|| { self.value.$method() })
}
}
}
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
, weight: Lazy<usize>
, line_count: Lazy<Line>
, line_weight: Lazy<Line>
, grapheme_count: Lazy<Grapheme>
, grapheme_weight: Lazy<Grapheme>
, pub value: Value
}
impl Node {
pub fn new(value: Value) -> Self {
Node { value: value, ..Default::default() }
}
pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
where Node: Measured<usize> {
assert!(self.len() >= span_len);
match **self {
Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
let span_i = or_zero!(i, left.len());
assert!(or_zero!(right.len(), span_i) >= span_len);
right.spanning(span_i, span_len)
}
, Branch { ref left, .. }
if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
, Leaf(_) | Branch {..} =>
(self, i)
}
}
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.strings()
.fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
}
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( f, "Node {{{}{}{}{:#?} }}"
, self.len.get().map(|l| format!("{} chars, ", l))
.unwrap_or_else(|| { String::new() })
, self.grapheme_count.get()
.map(|w| format!("{} graphemes, ", w.0))
.unwrap_or_else(|| { String::new() })
, self.line_count.get()
.map(|w| format!("{} lines, ", w.0))
.unwrap_or_else(|| { String::new() })
, self.value
)
}
}
impl convert::Into<NodeLink> for Node {
#[inline] fn into(self) -> NodeLink {
NodeLink::new(self)
}
}
impl ops::Deref for Node {
type Target = Value;
fn deref(&self) -> &Value { &self.value }
}
impl Measured<usize> for Node {
#[inline] fn to_byte_index(&self, index: usize) -> Option<usize> {
Some(index)
}
lazy_field!(measure, len, usize);
lazy_field!(measure_weight, weight, usize);
}
impl Measured<Grapheme> for Node {
#[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize> {
self.value.to_byte_index(index)
}
lazy_field!(measure, grapheme_count, Grapheme);
lazy_field!(measure_weight, grapheme_weight, Grapheme);
}
impl Measured<Line> for Node {
#[inline] fn to_byte_index(&self, index: Line) -> Option<usize> {
self.value.to_byte_index(index)
}
lazy_field!(measure, line_count, Line);
lazy_field!(measure_weight, line_weight, Line);
}
impl<M> ops::Index<M> for Node
where M: Metric
, Node: Measured<M>
, LeafRepr: Measured<M>
{
type Output = str;
fn index(&self, i: M) -> &str {
let len = self.measure();
assert!( i < len
, "Node::index: index {:?} out of bounds (length {:?})", i, len);
match **self {
Leaf(ref string) => {
let idx = string.to_byte_index(i)
.expect("index out of bounds!");
&string[idx..idx+1]
}
, Branch { ref right, .. } if len < i =>
&right[i - len]
, Branch { ref left, .. } => &left[i]
}
}
}
#[derive(Clone)]
pub enum Value {
Leaf(LeafRepr)
, Branch { left: NodeLink
, right: NodeLink }
}
impl Value {
#[inline]
pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
Branch { left: left, right: right }
}
}
impl<M> Measured<M> for Value
where M: Metric
, LeafRepr: Measured<M>
, Node: Measured<M>
{
fn to_byte_index(&self, index: M) -> Option<usize> {
match *self {
Leaf(ref r) => r.to_byte_index(index)
, Branch { ref left, ref right } =>
left.to_byte_index(index)
.or_else(|| { right.to_byte_index(index)
.map(|i| i + left.len() ) })
}
}
fn measure(&self) -> M {
match *self {
Leaf(ref r) => r.measure()
, Branch { ref left, ref right } =>
left.measure() + right.measure()
}
}
fn measure_weight(&self) -> M {
match *self {
Leaf(ref r) => r.measure_weight()
, Branch { ref left, .. } => left.measure()
}
}
}
impl convert::Into<Node> for Value {
#[inline] fn into(self) -> Node {
Node::new(self)
}
}
impl Default for Value {
fn default() -> Self {
Leaf(LeafRepr::default())
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Leaf(ref r) => write!(f, "Leaf({:?})", r)
, Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
, left
, right)
}
}
}