<commit_before>use super::*;

use std::{collections::BTreeSet, ops::Bound};

#[derive(Debug, Clone)]
pub(crate) struct View<'a> {
    pub(crate) pid: PageId,
    pub(crate) lo: &'a IVec,
    pub(crate) hi: &'a IVec,
    pub(crate) is_index: bool,
    pub(crate) next: Option<PageId>,
    pub(crate) ptr: TreePtr<'a>,
    frags: Vec<&'a Frag>,
    base_offset: usize,
    pub(crate) base_data: &'a Data,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl<'a> View<'a> {
    pub(crate) fn new(
        pid: PageId,
        ptr: TreePtr<'a>,
        frags: Vec<&'a Frag>,
    ) -> View<'a> {
        let mut view = View {
            pid,
            ptr,
            frags,
            lo: unsafe { std::mem::uninitialized() },
            hi: unsafe { std::mem::uninitialized() },
            is_index: false,
            base_offset: usize::max_value(),
            base_data: unsafe { std::mem::uninitialized() },
            next: None,
            merging_child: None,
            merging: false,
        };

        let mut merge_confirmed = false;

        for (offset, frag) in view.frags.iter().enumerate() {
            match frag {
                Frag::Base(node) => {
                    if view.base_offset == usize::max_value() {
                        // hi and next may be changed via a
                        // parent split if we re-add that frag
                        view.hi = &node.hi;
                        view.next = node.next;
                    }
                    view.lo = &node.lo;
                    view.is_index = node.data.index_ref().is_some();
                    view.base_offset = offset;
                    view.base_data = &node.data;
                    break;
                }
                Frag::ParentMergeIntention(pid) => {
                    if merge_confirmed {
                        merge_confirmed = false;
                    } else {
                        assert!(view.merging_child.is_none());
                        view.merging_child = Some(*pid);
                    }
                }
                Frag::ParentMergeConfirm => {
                    assert!(!merge_confirmed);
                    merge_confirmed = true;
                }
                Frag::ChildMergeCap => {
                    assert!(!view.merging);
                    assert_eq!(offset, 0);
                    view.merging = true;
                }
                _ => {}
            }
        }

        assert_ne!(
            view.base_offset,
            usize::max_value(),
            "view was never initialized with a base"
        );

        view
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.hi.is_empty(),
            Bound::Included(bound) => self.hi > bound || self.hi.is_empty(),
            Bound::Excluded(bound) => self.hi >= bound || self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.lo.is_empty(),
            Bound::Included(bound) | Bound::Excluded(bound) => self.lo <= bound,
        }
    }

    fn keys(&self) -> BTreeSet<&IVec> {
        let mut keys: BTreeSet<&IVec> = self
            .base_data
            .leaf_ref()
            .unwrap()
            .iter()
            .map(|(k, _v)| k)
            .collect();

        for offset in (0..self.base_offset).rev() {
            match self.frags[offset] {
                Frag::Set(k, _) => {
                    keys.insert(k);
                }
                Frag::Del(k) => {
                    keys.remove(k);
                }
                Frag::Merge(k, _) => {
                    keys.insert(k);
                }
                Frag::Base(_) => {
                    panic!(
                        "somehow hit 2 base nodes while \
                         searching for a successor"
                    );
                }
                Frag::ChildMergeCap => {}
                Frag::ParentMergeIntention(_) | Frag::ParentMergeConfirm => {
                    panic!(
                        "somehow hit parent merge \
                         frags while searching for a \
                         successor"
                    )
                }
            }
        }

        keys
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(self.lo, self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
        };

        let keys = self.keys();

        let successor_keys = keys.range(predecessor_key..);

        for encoded_key in successor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    prefix_encode(self.lo, &[255; 1024 * 1024])
                } else {
                    prefix_encode(self.lo, self.hi)
                }
            }
            Bound::Included(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
        };

        let keys = self.keys();

        let predecessor_keys = keys.range(..=successor_key).rev();

        for encoded_key in predecessor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn is_free(&self) -> bool {
        self.frags.is_empty()
    }

    pub(crate) fn leaf_value_for_key(
        &self,
        key: &[u8],
        config: &Config,
    ) -> Option<IVec> {
        assert!(!self.is_index);

        let mut merge_base = None;
        let mut merges = vec![];

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(k, val) if self.key_eq(k, key) => {
                    if merges.is_empty() {
                        return Some(val.clone());
                    } else {
                        merge_base = Some(val);
                        break;
                    }
                }
                Frag::Del(k) if self.key_eq(k, key) => return None,
                Frag::Merge(k, val) if self.key_eq(k, key) => merges.push(val),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.leaf_ref().expect("last_node should be a leaf");
                    let search = items
                        .binary_search_by(|&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        })
                        .ok();

                    let val = search.map(|idx| &items[idx].1);
                    if merges.is_empty() {
                        return val.cloned();
                    } else {
                        merge_base = val;
                    }
                }
                _ => {}
            }
        }

        if merges.is_empty() {
            None
        } else {
            let merge_fn_ptr = config
                .merge_operator
                .expect("must have a merge operator set");

            unsafe {
                let merge_fn: MergeOperator = std::mem::transmute(merge_fn_ptr);

                let mut ret = merge_fn(
                    key,
                    merge_base.map(|iv| &**iv),
                    &merges.pop().unwrap(),
                );
                                       ;
                for merge in merges.into_iter().rev() {
                    if let Some(v) = ret {
                        ret = merge_fn(key, Some(&*v), merge);
                    } else {
                        ret = merge_fn(key, None, merge);
                    }
                }

                ret.map(IVec::from)
            }
        }
    }

    #[inline]
    fn key_eq(&self, encoded: &[u8], not_encoded: &[u8]) -> bool {
        prefix_cmp_encoded(encoded, not_encoded, self.lo)
            == std::cmp::Ordering::Equal
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> PageId {
        assert!(self.is_index);

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(..) => unimplemented!(),
                Frag::Del(..) => unimplemented!(),
                Frag::Merge(..) => unimplemented!(),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.index_ref().expect("last_node should be a leaf");
                    let search =
                        binary_search_lub(items, |&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        });

                    // This might be none if ord is Less and we're
                    // searching for the empty key
                    let index = search.expect("failed to traverse index");

                    return items[index].1;
                }
                Frag::ParentMergeIntention(_)
                | Frag::ParentMergeConfirm
                | Frag::ChildMergeCap => {
                    // nothing to do for these frags
                }
            }
        }
        panic!("no index found")
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        let children = self.base_data.len();
        children > 2
            && self.size_in_bytes() > max_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn compact(&self, config: &Config) -> Node {
        let mut lhs = self.frags[self.base_offset].unwrap_base().clone();
        for offset in (0..self.base_offset).rev() {
            let frag = self.frags[offset];
            lhs.apply(frag, config.merge_operator);
        }
        lhs
    }

    pub(crate) fn split(&self, config: &Config) -> (Node, Node) {
        let mut lhs = self.compact(config);
        let rhs = lhs.split();

        lhs.data.drop_gte(&rhs.lo, &lhs.lo);
        lhs.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        lhs.next = None;

        (lhs, rhs)
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        // TODO needs to better account for
        // sizes that don't actually fall under
        // a merge threshold once we support one.
        self.frags[..self.base_offset + 1]
            .iter()
            .map(|f| f.size_in_bytes())
            .sum()
    }
}
<commit_msg>Properly account for hi keys being empty in the view hi member during reverse iteration<commit_after>use super::*;

use std::{collections::BTreeSet, ops::Bound};

#[derive(Debug, Clone)]
pub(crate) struct View<'a> {
    pub(crate) pid: PageId,
    pub(crate) lo: &'a IVec,
    pub(crate) hi: &'a IVec,
    pub(crate) is_index: bool,
    pub(crate) next: Option<PageId>,
    pub(crate) ptr: TreePtr<'a>,
    frags: Vec<&'a Frag>,
    base_offset: usize,
    pub(crate) base_data: &'a Data,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl<'a> View<'a> {
    pub(crate) fn new(
        pid: PageId,
        ptr: TreePtr<'a>,
        frags: Vec<&'a Frag>,
    ) -> View<'a> {
        let mut view = View {
            pid,
            ptr,
            frags,
            lo: unsafe { std::mem::uninitialized() },
            hi: unsafe { std::mem::uninitialized() },
            is_index: false,
            base_offset: usize::max_value(),
            base_data: unsafe { std::mem::uninitialized() },
            next: None,
            merging_child: None,
            merging: false,
        };

        let mut merge_confirmed = false;

        for (offset, frag) in view.frags.iter().enumerate() {
            match frag {
                Frag::Base(node) => {
                    if view.base_offset == usize::max_value() {
                        // hi and next may be changed via a
                        // parent split if we re-add that frag
                        view.hi = &node.hi;
                        view.next = node.next;
                    }
                    view.lo = &node.lo;
                    view.is_index = node.data.index_ref().is_some();
                    view.base_offset = offset;
                    view.base_data = &node.data;
                    break;
                }
                Frag::ParentMergeIntention(pid) => {
                    if merge_confirmed {
                        merge_confirmed = false;
                    } else {
                        assert!(view.merging_child.is_none());
                        view.merging_child = Some(*pid);
                    }
                }
                Frag::ParentMergeConfirm => {
                    assert!(!merge_confirmed);
                    merge_confirmed = true;
                }
                Frag::ChildMergeCap => {
                    assert!(!view.merging);
                    assert_eq!(offset, 0);
                    view.merging = true;
                }
                _ => {}
            }
        }

        assert_ne!(
            view.base_offset,
            usize::max_value(),
            "view was never initialized with a base"
        );

        view
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.hi.is_empty(),
            Bound::Included(bound) => self.hi > bound || self.hi.is_empty(),
            Bound::Excluded(bound) => self.hi >= bound || self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.lo.is_empty(),
            Bound::Included(bound) | Bound::Excluded(bound) => self.lo <= bound,
        }
    }

    fn keys(&self) -> BTreeSet<&IVec> {
        let mut keys: BTreeSet<&IVec> = self
            .base_data
            .leaf_ref()
            .unwrap()
            .iter()
            .map(|(k, _v)| k)
            .collect();

        for offset in (0..self.base_offset).rev() {
            match self.frags[offset] {
                Frag::Set(k, _) => {
                    keys.insert(k);
                }
                Frag::Del(k) => {
                    keys.remove(k);
                }
                Frag::Merge(k, _) => {
                    keys.insert(k);
                }
                Frag::Base(_) => {
                    panic!(
                        "somehow hit 2 base nodes while \
                         searching for a successor"
                    );
                }
                Frag::ChildMergeCap => {}
                Frag::ParentMergeIntention(_) | Frag::ParentMergeConfirm => {
                    panic!(
                        "somehow hit parent merge \
                         frags while searching for a \
                         successor"
                    )
                }
            }
        }

        keys
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(self.lo, self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
        };

        let keys = self.keys();

        let successor_keys = keys.range(predecessor_key..);

        for encoded_key in successor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    prefix_encode(self.lo, &[255; 1024 * 1024])
                } else {
                    prefix_encode(self.lo, self.hi)
                }
            }
            Bound::Included(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, self.hi)
                };
                prefix_encode(self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, self.hi)
                };
                prefix_encode(self.lo, min)
            }
        };

        let keys = self.keys();

        let predecessor_keys = keys.range(..=successor_key).rev();

        for encoded_key in predecessor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn is_free(&self) -> bool {
        self.frags.is_empty()
    }

    pub(crate) fn leaf_value_for_key(
        &self,
        key: &[u8],
        config: &Config,
    ) -> Option<IVec> {
        assert!(!self.is_index);

        let mut merge_base = None;
        let mut merges = vec![];

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(k, val) if self.key_eq(k, key) => {
                    if merges.is_empty() {
                        return Some(val.clone());
                    } else {
                        merge_base = Some(val);
                        break;
                    }
                }
                Frag::Del(k) if self.key_eq(k, key) => return None,
                Frag::Merge(k, val) if self.key_eq(k, key) => merges.push(val),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.leaf_ref().expect("last_node should be a leaf");
                    let search = items
                        .binary_search_by(|&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        })
                        .ok();

                    let val = search.map(|idx| &items[idx].1);
                    if merges.is_empty() {
                        return val.cloned();
                    } else {
                        merge_base = val;
                    }
                }
                _ => {}
            }
        }

        if merges.is_empty() {
            None
        } else {
            let merge_fn_ptr = config
                .merge_operator
                .expect("must have a merge operator set");

            unsafe {
                let merge_fn: MergeOperator = std::mem::transmute(merge_fn_ptr);

                let mut ret = merge_fn(
                    key,
                    merge_base.map(|iv| &**iv),
                    &merges.pop().unwrap(),
                );
                                       ;
                for merge in merges.into_iter().rev() {
                    if let Some(v) = ret {
                        ret = merge_fn(key, Some(&*v), merge);
                    } else {
                        ret = merge_fn(key, None, merge);
                    }
                }

                ret.map(IVec::from)
            }
        }
    }

    #[inline]
    fn key_eq(&self, encoded: &[u8], not_encoded: &[u8]) -> bool {
        prefix_cmp_encoded(encoded, not_encoded, self.lo)
            == std::cmp::Ordering::Equal
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> PageId {
        assert!(self.is_index);

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(..) => unimplemented!(),
                Frag::Del(..) => unimplemented!(),
                Frag::Merge(..) => unimplemented!(),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.index_ref().expect("last_node should be a leaf");
                    let search =
                        binary_search_lub(items, |&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        });

                    // This might be none if ord is Less and we're
                    // searching for the empty key
                    let index = search.expect("failed to traverse index");

                    return items[index].1;
                }
                Frag::ParentMergeIntention(_)
                | Frag::ParentMergeConfirm
                | Frag::ChildMergeCap => {
                    // nothing to do for these frags
                }
            }
        }
        panic!("no index found")
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        let children = self.base_data.len();
        children > 2
            && self.size_in_bytes() > max_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn compact(&self, config: &Config) -> Node {
        let mut lhs = self.frags[self.base_offset].unwrap_base().clone();
        for offset in (0..self.base_offset).rev() {
            let frag = self.frags[offset];
            lhs.apply(frag, config.merge_operator);
        }
        lhs
    }

    pub(crate) fn split(&self, config: &Config) -> (Node, Node) {
        let mut lhs = self.compact(config);
        let rhs = lhs.split();

        lhs.data.drop_gte(&rhs.lo, &lhs.lo);
        lhs.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        lhs.next = None;

        (lhs, rhs)
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        // TODO needs to better account for
        // sizes that don't actually fall under
        // a merge threshold once we support one.
        self.frags[..self.base_offset + 1]
            .iter()
            .map(|f| f.size_in_bytes())
            .sum()
    }
}
<|endoftext|>


<commit_before>//! JSON Errors
//!
//! This module is centered around the `Error` and `ErrorCode` types, which represents all possible
//! `serde_json` errors.

use std::error;
use std::fmt;
use std::io;
use std::result;
use std::string::FromUtf8Error;

use serde::de;
use serde::ser;

/// The errors that can arise while parsing a JSON stream.
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
    /// Catchall for syntax error messages
    Custom(String),

    /// Incorrect type from value
    InvalidType(de::Type),

    /// Incorrect value
    InvalidValue(String),

    /// Invalid length
    InvalidLength(usize),

    /// Unknown variant in an enum.
    UnknownVariant(String),

    /// Unknown field in struct.
    UnknownField(String),

    /// Struct is missing a field.
    MissingField(&'static str),

    /// EOF while parsing a list.
    EOFWhileParsingList,

    /// EOF while parsing an object.
    EOFWhileParsingObject,

    /// EOF while parsing a string.
    EOFWhileParsingString,

    /// EOF while parsing a JSON value.
    EOFWhileParsingValue,

    /// Expected this character to be a `':'`.
    ExpectedColon,

    /// Expected this character to be either a `','` or a `]`.
    ExpectedListCommaOrEnd,

    /// Expected this character to be either a `','` or a `}`.
    ExpectedObjectCommaOrEnd,

    /// Expected to parse either a `true`, `false`, or a `null`.
    ExpectedSomeIdent,

    /// Expected this character to start a JSON value.
    ExpectedSomeValue,

    /// Invalid hex escape code.
    InvalidEscape,

    /// Invalid number.
    InvalidNumber,

    /// Invalid unicode code point.
    InvalidUnicodeCodePoint,

    /// Object key is not a string.
    KeyMustBeAString,

    /// Lone leading surrogate in hex escape.
    LoneLeadingSurrogateInHexEscape,

    /// JSON has non-whitespace trailing characters after the value.
    TrailingCharacters,

    /// Unexpected end of hex excape.
    UnexpectedEndOfHexEscape,
}

impl fmt::Debug for ErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::fmt::Debug;

        match *self {
            ErrorCode::Custom(ref msg) => write!(f, "{}", msg),
            ErrorCode::InvalidType(ref ty) => write!(f, "invalid type: {:?}", ty),
            ErrorCode::InvalidValue(ref msg) => write!(f, "invalid value: {}", msg),
            ErrorCode::InvalidLength(ref len) => write!(f, "invalid value length {}", len),
            ErrorCode::UnknownVariant(ref variant) => write!(f, "unknown variant \"{}\"", variant),
            ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
            ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
            ErrorCode::EOFWhileParsingList => "EOF while parsing a list".fmt(f),
            ErrorCode::EOFWhileParsingObject => "EOF while parsing an object".fmt(f),
            ErrorCode::EOFWhileParsingString => "EOF while parsing a string".fmt(f),
            ErrorCode::EOFWhileParsingValue => "EOF while parsing a value".fmt(f),
            ErrorCode::ExpectedColon => "expected `:`".fmt(f),
            ErrorCode::ExpectedListCommaOrEnd => "expected `,` or `]`".fmt(f),
            ErrorCode::ExpectedObjectCommaOrEnd => "expected `,` or `}`".fmt(f),
            ErrorCode::ExpectedSomeIdent => "expected ident".fmt(f),
            ErrorCode::ExpectedSomeValue => "expected value".fmt(f),
            ErrorCode::InvalidEscape => "invalid escape".fmt(f),
            ErrorCode::InvalidNumber => "invalid number".fmt(f),
            ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
            ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
            ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
            ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
            ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
        }
    }
}

/// This type represents all possible errors that can occur when serializing or deserializing a
/// value into JSON.
#[derive(Debug)]
pub enum Error {
    /// The JSON value had some syntatic error.
    Syntax(ErrorCode, usize, usize),

    /// Some IO error occurred when serializing or deserializing a value.
    Io(io::Error),

    /// Some UTF8 error occurred while serializing or deserializing a value.
    FromUtf8(FromUtf8Error),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(..) => "syntax error",
            Error::Io(ref error) => error::Error::description(error),
            Error::FromUtf8(ref error) => error.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref error) => Some(error),
            Error::FromUtf8(ref error) => Some(error),
            _ => None,
        }
    }

}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref code, line, col) => {
                write!(fmt, "{:?} at line {} column {}", code, line, col)
            }
            Error::Io(ref error) => fmt::Display::fmt(error, fmt),
            Error::FromUtf8(ref error) => fmt::Display::fmt(error, fmt),
        }
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error::Io(error)
    }
}

impl From<FromUtf8Error> for Error {
    fn from(error: FromUtf8Error) -> Error {
        Error::FromUtf8(error)
    }
}

impl From<de::value::Error> for Error {
    fn from(error: de::value::Error) -> Error {
        match error {
            de::value::Error::Custom(e) => {
                Error::Syntax(ErrorCode::Custom(e), 0, 0)
            }
            de::value::Error::EndOfStream => {
                de::Error::end_of_stream()
            }
            de::value::Error::InvalidType(ty) => {
                Error::Syntax(ErrorCode::InvalidType(ty), 0, 0)
            }
            de::value::Error::InvalidValue(msg) => {
                Error::Syntax(ErrorCode::InvalidValue(msg), 0, 0)
            }
            de::value::Error::InvalidLength(len) => {
                Error::Syntax(ErrorCode::InvalidLength(len), 0, 0)
            }
            de::value::Error::UnknownVariant(variant) => {
                Error::Syntax(ErrorCode::UnknownVariant(variant), 0, 0)
            }
            de::value::Error::UnknownField(field) => {
                Error::Syntax(ErrorCode::UnknownField(field), 0, 0)
            }
            de::value::Error::MissingField(field) => {
                Error::Syntax(ErrorCode::MissingField(field), 0, 0)
            }
        }
    }
}

impl de::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Syntax(ErrorCode::Custom(msg.into()), 0, 0)
    }

    fn end_of_stream() -> Error {
        Error::Syntax(ErrorCode::EOFWhileParsingValue, 0, 0)
    }

    fn invalid_type(ty: de::Type) -> Error {
        Error::Syntax(ErrorCode::InvalidType(ty), 0, 0)
    }

    fn invalid_value(msg: &str) -> Error {
        Error::Syntax(ErrorCode::InvalidValue(msg.to_owned()), 0, 0)
    }

    fn invalid_length(len: usize) -> Error {
        Error::Syntax(ErrorCode::InvalidLength(len), 0, 0)
    }

    fn unknown_variant(variant: &str) -> Error {
        Error::Syntax(ErrorCode::UnknownVariant(String::from(variant)), 0, 0)
    }

    fn unknown_field(field: &str) -> Error {
        Error::Syntax(ErrorCode::UnknownField(String::from(field)), 0, 0)
    }

    fn missing_field(field: &'static str) -> Error {
        Error::Syntax(ErrorCode::MissingField(field), 0, 0)
    }
}

impl ser::Error for Error {
    /// Raised when there is general error when deserializing a type.
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Syntax(ErrorCode::Custom(msg.into()), 0, 0)
    }
}

/// Helper alias for `Result` objects that return a JSON `Error`.
pub type Result<T> = result::Result<T, Error>;
<commit_msg>Fix a warning<commit_after>//! JSON Errors
//!
//! This module is centered around the `Error` and `ErrorCode` types, which represents all possible
//! `serde_json` errors.

use std::error;
use std::fmt;
use std::io;
use std::result;
use std::string::FromUtf8Error;

use serde::de;
use serde::ser;

/// The errors that can arise while parsing a JSON stream.
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
    /// Catchall for syntax error messages
    Custom(String),

    /// Incorrect type from value
    InvalidType(de::Type),

    /// Incorrect value
    InvalidValue(String),

    /// Invalid length
    InvalidLength(usize),

    /// Unknown variant in an enum.
    UnknownVariant(String),

    /// Unknown field in struct.
    UnknownField(String),

    /// Struct is missing a field.
    MissingField(&'static str),

    /// EOF while parsing a list.
    EOFWhileParsingList,

    /// EOF while parsing an object.
    EOFWhileParsingObject,

    /// EOF while parsing a string.
    EOFWhileParsingString,

    /// EOF while parsing a JSON value.
    EOFWhileParsingValue,

    /// Expected this character to be a `':'`.
    ExpectedColon,

    /// Expected this character to be either a `','` or a `]`.
    ExpectedListCommaOrEnd,

    /// Expected this character to be either a `','` or a `}`.
    ExpectedObjectCommaOrEnd,

    /// Expected to parse either a `true`, `false`, or a `null`.
    ExpectedSomeIdent,

    /// Expected this character to start a JSON value.
    ExpectedSomeValue,

    /// Invalid hex escape code.
    InvalidEscape,

    /// Invalid number.
    InvalidNumber,

    /// Invalid unicode code point.
    InvalidUnicodeCodePoint,

    /// Object key is not a string.
    KeyMustBeAString,

    /// Lone leading surrogate in hex escape.
    LoneLeadingSurrogateInHexEscape,

    /// JSON has non-whitespace trailing characters after the value.
    TrailingCharacters,

    /// Unexpected end of hex excape.
    UnexpectedEndOfHexEscape,
}

impl fmt::Debug for ErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorCode::Custom(ref msg) => write!(f, "{}", msg),
            ErrorCode::InvalidType(ref ty) => write!(f, "invalid type: {:?}", ty),
            ErrorCode::InvalidValue(ref msg) => write!(f, "invalid value: {}", msg),
            ErrorCode::InvalidLength(ref len) => write!(f, "invalid value length {}", len),
            ErrorCode::UnknownVariant(ref variant) => write!(f, "unknown variant \"{}\"", variant),
            ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
            ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
            ErrorCode::EOFWhileParsingList => "EOF while parsing a list".fmt(f),
            ErrorCode::EOFWhileParsingObject => "EOF while parsing an object".fmt(f),
            ErrorCode::EOFWhileParsingString => "EOF while parsing a string".fmt(f),
            ErrorCode::EOFWhileParsingValue => "EOF while parsing a value".fmt(f),
            ErrorCode::ExpectedColon => "expected `:`".fmt(f),
            ErrorCode::ExpectedListCommaOrEnd => "expected `,` or `]`".fmt(f),
            ErrorCode::ExpectedObjectCommaOrEnd => "expected `,` or `}`".fmt(f),
            ErrorCode::ExpectedSomeIdent => "expected ident".fmt(f),
            ErrorCode::ExpectedSomeValue => "expected value".fmt(f),
            ErrorCode::InvalidEscape => "invalid escape".fmt(f),
            ErrorCode::InvalidNumber => "invalid number".fmt(f),
            ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
            ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
            ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
            ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
            ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
        }
    }
}

/// This type represents all possible errors that can occur when serializing or deserializing a
/// value into JSON.
#[derive(Debug)]
pub enum Error {
    /// The JSON value had some syntatic error.
    Syntax(ErrorCode, usize, usize),

    /// Some IO error occurred when serializing or deserializing a value.
    Io(io::Error),

    /// Some UTF8 error occurred while serializing or deserializing a value.
    FromUtf8(FromUtf8Error),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(..) => "syntax error",
            Error::Io(ref error) => error::Error::description(error),
            Error::FromUtf8(ref error) => error.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref error) => Some(error),
            Error::FromUtf8(ref error) => Some(error),
            _ => None,
        }
    }

}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref code, line, col) => {
                write!(fmt, "{:?} at line {} column {}", code, line, col)
            }
            Error::Io(ref error) => fmt::Display::fmt(error, fmt),
            Error::FromUtf8(ref error) => fmt::Display::fmt(error, fmt),
        }
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error::Io(error)
    }
}

impl From<FromUtf8Error> for Error {
    fn from(error: FromUtf8Error) -> Error {
        Error::FromUtf8(error)
    }
}

impl From<de::value::Error> for Error {
    fn from(error: de::value::Error) -> Error {
        match error {
            de::value::Error::Custom(e) => {
                Error::Syntax(ErrorCode::Custom(e), 0, 0)
            }
            de::value::Error::EndOfStream => {
                de::Error::end_of_stream()
            }
            de::value::Error::InvalidType(ty) => {
                Error::Syntax(ErrorCode::InvalidType(ty), 0, 0)
            }
            de::value::Error::InvalidValue(msg) => {
                Error::Syntax(ErrorCode::InvalidValue(msg), 0, 0)
            }
            de::value::Error::InvalidLength(len) => {
                Error::Syntax(ErrorCode::InvalidLength(len), 0, 0)
            }
            de::value::Error::UnknownVariant(variant) => {
                Error::Syntax(ErrorCode::UnknownVariant(variant), 0, 0)
            }
            de::value::Error::UnknownField(field) => {
                Error::Syntax(ErrorCode::UnknownField(field), 0, 0)
            }
            de::value::Error::MissingField(field) => {
                Error::Syntax(ErrorCode::MissingField(field), 0, 0)
            }
        }
    }
}

impl de::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Syntax(ErrorCode::Custom(msg.into()), 0, 0)
    }

    fn end_of_stream() -> Error {
        Error::Syntax(ErrorCode::EOFWhileParsingValue, 0, 0)
    }

    fn invalid_type(ty: de::Type) -> Error {
        Error::Syntax(ErrorCode::InvalidType(ty), 0, 0)
    }

    fn invalid_value(msg: &str) -> Error {
        Error::Syntax(ErrorCode::InvalidValue(msg.to_owned()), 0, 0)
    }

    fn invalid_length(len: usize) -> Error {
        Error::Syntax(ErrorCode::InvalidLength(len), 0, 0)
    }

    fn unknown_variant(variant: &str) -> Error {
        Error::Syntax(ErrorCode::UnknownVariant(String::from(variant)), 0, 0)
    }

    fn unknown_field(field: &str) -> Error {
        Error::Syntax(ErrorCode::UnknownField(String::from(field)), 0, 0)
    }

    fn missing_field(field: &'static str) -> Error {
        Error::Syntax(ErrorCode::MissingField(field), 0, 0)
    }
}

impl ser::Error for Error {
    /// Raised when there is general error when deserializing a type.
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Syntax(ErrorCode::Custom(msg.into()), 0, 0)
    }
}

/// Helper alias for `Result` objects that return a JSON `Error`.
pub type Result<T> = result::Result<T, Error>;
<|endoftext|>


<commit_before>use bs58;
use sodiumoxide::crypto::sign;
use sodiumoxide::randombytes;
use std::fmt;

use super::error::*;
use super::sigpair::*;
use super::util::*;

pub const PUB_ADDRESS_PREFIX: &str = "GOD";
const PRIV_BUF_PREFIX: u8 = 0x01;
const PUB_BUF_PREFIX: u8 = 0x02;

pub trait Wif<T, U> {
    fn from_wif(s: &str) -> Result<T, WifError>;
    fn to_wif(&self) -> U;
}

pub struct PrivateWif(Box<str>);

impl fmt::Display for PrivateWif {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", &*self.0)
    }
}

impl std::ops::Deref for PrivateWif {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

impl std::ops::Drop for PrivateWif {
    fn drop(&mut self) {
        let bytes = unsafe { self.0.as_bytes_mut() };
        sodiumoxide::utils::memzero(bytes);
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PublicKey(pub(crate) sign::PublicKey);

impl PublicKey {
    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        sign::verify_detached(sig, msg, &self.0)
    }

    #[inline]
    pub fn from_slice(bytes: &[u8]) -> Option<PublicKey> {
        let key = sign::PublicKey::from_slice(bytes)?;
        Some(PublicKey(key))
    }
}

impl Wif<PublicKey, Box<str>> for PublicKey {
    fn from_wif(s: &str) -> Result<PublicKey, WifError> {
        if s.len() < 3 || &s[0..3] != PUB_ADDRESS_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }
        let raw = match bs58::decode(&s[3..]).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PUB_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let prefixed_key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(prefixed_key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let key = &prefixed_key[1..prefixed_key.len()];
        Ok(PublicKey(sign::PublicKey::from_slice(key).unwrap()))
    }

    fn to_wif(&self) -> Box<str> {
        let mut buf: Vec<u8> = Vec::<u8>::with_capacity(37);
        buf.push(PUB_BUF_PREFIX);
        buf.extend_from_slice(self.0.as_ref());

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        let mut s = bs58::encode(buf).into_string();
        s.insert_str(0, PUB_ADDRESS_PREFIX);
        s.into_boxed_str()
    }
}

impl AsRef<[u8]> for PublicKey {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

#[derive(Debug, Clone)]
pub struct PrivateKey {
    seed: sign::Seed,
    key: sign::SecretKey,
}

impl PrivateKey {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> sign::Signature {
        sign::sign_detached(msg, &self.key)
    }

    #[inline]
    pub fn from_slice(seed: &[u8], key: &[u8]) -> Option<PrivateKey> {
        Some(PrivateKey {
            seed: sign::Seed::from_slice(seed)?,
            key: sign::SecretKey::from_slice(key)?,
        })
    }
}

impl Wif<KeyPair, PrivateWif> for PrivateKey {
    fn from_wif(s: &str) -> Result<KeyPair, WifError> {
        let raw = match bs58::decode(s).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PRIV_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let seed = sign::Seed::from_slice(&key[1..]).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        Ok(KeyPair(PublicKey(pk), PrivateKey { seed, key: sk }))
    }

    fn to_wif(&self) -> PrivateWif {
        let mut buf = Vec::<u8>::with_capacity(37);
        buf.push(PRIV_BUF_PREFIX);
        buf.extend_from_slice(&self.seed.0);

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        PrivateWif(bs58::encode(buf).into_string().into_boxed_str())
    }
}

#[derive(Debug, Clone)]
pub struct KeyPair(pub PublicKey, pub PrivateKey);

impl KeyPair {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> SigPair {
        SigPair {
            pub_key: self.0.clone(),
            signature: self.1.sign(msg),
        }
    }

    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        PublicKey::verify(&self.0, msg, sig)
    }

    pub fn gen_keypair() -> KeyPair {
        let mut raw_seed: [u8; sign::SEEDBYTES] = [0; sign::SEEDBYTES];
        randombytes::randombytes_into(&mut raw_seed);
        let seed = sign::Seed::from_slice(&raw_seed).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        KeyPair(PublicKey(pk), PrivateKey { seed, key: sk })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_and_recover_keys() {
        let kp = KeyPair::gen_keypair();

        let pk = &*kp.0.to_wif();
        assert_eq!(&*PublicKey::from_wif(pk).unwrap().to_wif(), pk);

        let sk = &*kp.1.to_wif();
        assert_eq!(&*PrivateKey::from_wif(sk).unwrap().1.to_wif(), sk);
    }

    #[test]
    fn test_import_keys_from_wif() {
        let kp =
            PrivateKey::from_wif("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM").unwrap();
        assert_eq!(
            &*kp.1.to_wif(),
            "3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM"
        );
        assert_eq!(
            &*kp.0.to_wif(),
            "GOD52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8"
        );
    }

    #[test]
    fn test_invalid_prefix() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );
    }

    #[test]
    fn test_invalid_checksum() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );
    }

    #[test]
    fn test_sign_message() {
        let msg = "Hello world!".as_bytes();
        let kp = KeyPair::gen_keypair();

        let sig = &kp.1.sign(msg);
        assert!(kp.0.verify(msg, sig));

        let pair = SigPair {
            pub_key: kp.0,
            signature: *sig,
        };
        assert!(pair.verify(msg));

        // Test bad keys
        let kp = KeyPair::gen_keypair();
        assert!(!kp.verify(msg, sig));
    }
}
<commit_msg>Derive PartialEq on PrivateKey<commit_after>use bs58;
use sodiumoxide::crypto::sign;
use sodiumoxide::randombytes;
use std::fmt;

use super::error::*;
use super::sigpair::*;
use super::util::*;

pub const PUB_ADDRESS_PREFIX: &str = "GOD";
const PRIV_BUF_PREFIX: u8 = 0x01;
const PUB_BUF_PREFIX: u8 = 0x02;

pub trait Wif<T, U> {
    fn from_wif(s: &str) -> Result<T, WifError>;
    fn to_wif(&self) -> U;
}

pub struct PrivateWif(Box<str>);

impl fmt::Display for PrivateWif {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", &*self.0)
    }
}

impl std::ops::Deref for PrivateWif {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

impl std::ops::Drop for PrivateWif {
    fn drop(&mut self) {
        let bytes = unsafe { self.0.as_bytes_mut() };
        sodiumoxide::utils::memzero(bytes);
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PublicKey(pub(crate) sign::PublicKey);

impl PublicKey {
    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        sign::verify_detached(sig, msg, &self.0)
    }

    #[inline]
    pub fn from_slice(bytes: &[u8]) -> Option<PublicKey> {
        let key = sign::PublicKey::from_slice(bytes)?;
        Some(PublicKey(key))
    }
}

impl Wif<PublicKey, Box<str>> for PublicKey {
    fn from_wif(s: &str) -> Result<PublicKey, WifError> {
        if s.len() < 3 || &s[0..3] != PUB_ADDRESS_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }
        let raw = match bs58::decode(&s[3..]).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PUB_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let prefixed_key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(prefixed_key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let key = &prefixed_key[1..prefixed_key.len()];
        Ok(PublicKey(sign::PublicKey::from_slice(key).unwrap()))
    }

    fn to_wif(&self) -> Box<str> {
        let mut buf: Vec<u8> = Vec::<u8>::with_capacity(37);
        buf.push(PUB_BUF_PREFIX);
        buf.extend_from_slice(self.0.as_ref());

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        let mut s = bs58::encode(buf).into_string();
        s.insert_str(0, PUB_ADDRESS_PREFIX);
        s.into_boxed_str()
    }
}

impl AsRef<[u8]> for PublicKey {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PrivateKey {
    seed: sign::Seed,
    key: sign::SecretKey,
}

impl PrivateKey {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> sign::Signature {
        sign::sign_detached(msg, &self.key)
    }

    #[inline]
    pub fn from_slice(seed: &[u8], key: &[u8]) -> Option<PrivateKey> {
        Some(PrivateKey {
            seed: sign::Seed::from_slice(seed)?,
            key: sign::SecretKey::from_slice(key)?,
        })
    }
}

impl Wif<KeyPair, PrivateWif> for PrivateKey {
    fn from_wif(s: &str) -> Result<KeyPair, WifError> {
        let raw = match bs58::decode(s).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PRIV_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let seed = sign::Seed::from_slice(&key[1..]).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        Ok(KeyPair(PublicKey(pk), PrivateKey { seed, key: sk }))
    }

    fn to_wif(&self) -> PrivateWif {
        let mut buf = Vec::<u8>::with_capacity(37);
        buf.push(PRIV_BUF_PREFIX);
        buf.extend_from_slice(&self.seed.0);

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        PrivateWif(bs58::encode(buf).into_string().into_boxed_str())
    }
}

#[derive(Debug, Clone)]
pub struct KeyPair(pub PublicKey, pub PrivateKey);

impl KeyPair {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> SigPair {
        SigPair {
            pub_key: self.0.clone(),
            signature: self.1.sign(msg),
        }
    }

    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        PublicKey::verify(&self.0, msg, sig)
    }

    pub fn gen_keypair() -> KeyPair {
        let mut raw_seed: [u8; sign::SEEDBYTES] = [0; sign::SEEDBYTES];
        randombytes::randombytes_into(&mut raw_seed);
        let seed = sign::Seed::from_slice(&raw_seed).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        KeyPair(PublicKey(pk), PrivateKey { seed, key: sk })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_and_recover_keys() {
        let kp = KeyPair::gen_keypair();

        let pk = &*kp.0.to_wif();
        assert_eq!(&*PublicKey::from_wif(pk).unwrap().to_wif(), pk);

        let sk = &*kp.1.to_wif();
        assert_eq!(&*PrivateKey::from_wif(sk).unwrap().1.to_wif(), sk);
    }

    #[test]
    fn test_import_keys_from_wif() {
        let kp =
            PrivateKey::from_wif("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM").unwrap();
        assert_eq!(
            &*kp.1.to_wif(),
            "3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM"
        );
        assert_eq!(
            &*kp.0.to_wif(),
            "GOD52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8"
        );
    }

    #[test]
    fn test_invalid_prefix() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );
    }

    #[test]
    fn test_invalid_checksum() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );
    }

    #[test]
    fn test_sign_message() {
        let msg = "Hello world!".as_bytes();
        let kp = KeyPair::gen_keypair();

        let sig = &kp.1.sign(msg);
        assert!(kp.0.verify(msg, sig));

        let pair = SigPair {
            pub_key: kp.0,
            signature: *sig,
        };
        assert!(pair.verify(msg));

        // Test bad keys
        let kp = KeyPair::gen_keypair();
        assert!(!kp.verify(msg, sig));
    }
}
<|endoftext|>


<commit_before>//! When *constructing* `hir`, we start at some parent syntax node and recursively
//! lower the children.
//!
//! This modules allows one to go in the opposite direction: start with a syntax
//! node for a *child*, and get its hir.

use either::Either;

use crate::{
    db::DefDatabase,
    dyn_map::DynMap,
    keys,
    src::{HasChildSource, HasSource},
    AdtId, AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId,
    StructFieldId, TraitId, VariantId,
};

pub trait ChildBySource {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap;
}

impl ChildBySource for TraitId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let data = db.trait_data(*self);
        for (_name, item) in data.items.iter() {
            match *item {
                AssocItemId::FunctionId(func) => {
                    let src = func.lookup(db).source(db);
                    res[keys::FUNCTION].insert(src, func)
                }
                AssocItemId::ConstId(konst) => {
                    let src = konst.lookup(db).source(db);
                    res[keys::CONST].insert(src, konst)
                }
                AssocItemId::TypeAliasId(ty) => {
                    let src = ty.lookup(db).source(db);
                    res[keys::TYPE_ALIAS].insert(src, ty)
                }
            }
        }

        res
    }
}

impl ChildBySource for ImplId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let data = db.impl_data(*self);
        for &item in data.items.iter() {
            match item {
                AssocItemId::FunctionId(func) => {
                    let src = func.lookup(db).source(db);
                    res[keys::FUNCTION].insert(src, func)
                }
                AssocItemId::ConstId(konst) => {
                    let src = konst.lookup(db).source(db);
                    res[keys::CONST].insert(src, konst)
                }
                AssocItemId::TypeAliasId(ty) => {
                    let src = ty.lookup(db).source(db);
                    res[keys::TYPE_ALIAS].insert(src, ty)
                }
            }
        }

        res
    }
}

impl ChildBySource for ModuleId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let crate_def_map = db.crate_def_map(self.krate);
        for item in crate_def_map[self.local_id].scope.declarations() {
            match item {
                ModuleDefId::FunctionId(func) => {
                    let src = func.lookup(db).source(db);
                    res[keys::FUNCTION].insert(src, func)
                }
                ModuleDefId::ConstId(konst) => {
                    let src = konst.lookup(db).source(db);
                    res[keys::CONST].insert(src, konst)
                }
                ModuleDefId::StaticId(statik) => {
                    let src = statik.lookup(db).source(db);
                    res[keys::STATIC].insert(src, statik)
                }
                ModuleDefId::TypeAliasId(ty) => {
                    let src = ty.lookup(db).source(db);
                    res[keys::TYPE_ALIAS].insert(src, ty)
                }
                ModuleDefId::TraitId(trait_) => {
                    let src = trait_.lookup(db).source(db);
                    res[keys::TRAIT].insert(src, trait_)
                }
                ModuleDefId::AdtId(adt) => match adt {
                    AdtId::StructId(strukt) => {
                        let src = strukt.lookup(db).source(db);
                        res[keys::STRUCT].insert(src, strukt)
                    }
                    AdtId::UnionId(union_) => {
                        let src = union_.lookup(db).source(db);
                        res[keys::UNION].insert(src, union_)
                    }
                    AdtId::EnumId(enum_) => {
                        let src = enum_.lookup(db).source(db);
                        res[keys::ENUM].insert(src, enum_)
                    }
                },
                _ => (),
            }
        }

        for &impl_ in crate_def_map[self.local_id].impls.iter() {
            let src = impl_.lookup(db).source(db);
            res[keys::IMPL].insert(src, impl_)
        }

        res
    }
}

impl ChildBySource for VariantId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = StructFieldId { parent: *self, local_id };
            match source {
                Either::Left(source) => {
                    res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id)
                }
                Either::Right(source) => {
                    res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id)
                }
            }
        }
        res
    }
}

impl ChildBySource for EnumId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = EnumVariantId { parent: *self, local_id };
            res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id)
        }

        res
    }
}
<commit_msg>Implement ChildBySource for DefWithBody<commit_after>//! When *constructing* `hir`, we start at some parent syntax node and recursively
//! lower the children.
//!
//! This modules allows one to go in the opposite direction: start with a syntax
//! node for a *child*, and get its hir.

use either::Either;

use crate::{
    db::DefDatabase,
    dyn_map::DynMap,
    keys,
    src::{HasChildSource, HasSource},
    AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId,
    ModuleId, StructFieldId, TraitId, VariantId,
};

pub trait ChildBySource {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap;
}

impl ChildBySource for TraitId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let data = db.trait_data(*self);
        for (_name, item) in data.items.iter() {
            match *item {
                AssocItemId::FunctionId(func) => {
                    let src = func.lookup(db).source(db);
                    res[keys::FUNCTION].insert(src, func)
                }
                AssocItemId::ConstId(konst) => {
                    let src = konst.lookup(db).source(db);
                    res[keys::CONST].insert(src, konst)
                }
                AssocItemId::TypeAliasId(ty) => {
                    let src = ty.lookup(db).source(db);
                    res[keys::TYPE_ALIAS].insert(src, ty)
                }
            }
        }

        res
    }
}

impl ChildBySource for ImplId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let data = db.impl_data(*self);
        for &item in data.items.iter() {
            match item {
                AssocItemId::FunctionId(func) => {
                    let src = func.lookup(db).source(db);
                    res[keys::FUNCTION].insert(src, func)
                }
                AssocItemId::ConstId(konst) => {
                    let src = konst.lookup(db).source(db);
                    res[keys::CONST].insert(src, konst)
                }
                AssocItemId::TypeAliasId(ty) => {
                    let src = ty.lookup(db).source(db);
                    res[keys::TYPE_ALIAS].insert(src, ty)
                }
            }
        }

        res
    }
}

impl ChildBySource for ModuleId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let crate_def_map = db.crate_def_map(self.krate);
        let module_data = &crate_def_map[self.local_id];

        module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item));

        for &impl_ in module_data.impls.iter() {
            let src = impl_.lookup(db).source(db);
            res[keys::IMPL].insert(src, impl_)
        }

        res
    }
}

fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) {
    match item {
        ModuleDefId::FunctionId(func) => {
            let src = func.lookup(db).source(db);
            map[keys::FUNCTION].insert(src, func)
        }
        ModuleDefId::ConstId(konst) => {
            let src = konst.lookup(db).source(db);
            map[keys::CONST].insert(src, konst)
        }
        ModuleDefId::StaticId(statik) => {
            let src = statik.lookup(db).source(db);
            map[keys::STATIC].insert(src, statik)
        }
        ModuleDefId::TypeAliasId(ty) => {
            let src = ty.lookup(db).source(db);
            map[keys::TYPE_ALIAS].insert(src, ty)
        }
        ModuleDefId::TraitId(trait_) => {
            let src = trait_.lookup(db).source(db);
            map[keys::TRAIT].insert(src, trait_)
        }
        ModuleDefId::AdtId(adt) => match adt {
            AdtId::StructId(strukt) => {
                let src = strukt.lookup(db).source(db);
                map[keys::STRUCT].insert(src, strukt)
            }
            AdtId::UnionId(union_) => {
                let src = union_.lookup(db).source(db);
                map[keys::UNION].insert(src, union_)
            }
            AdtId::EnumId(enum_) => {
                let src = enum_.lookup(db).source(db);
                map[keys::ENUM].insert(src, enum_)
            }
        },
        _ => (),
    }
}

impl ChildBySource for VariantId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = StructFieldId { parent: *self, local_id };
            match source {
                Either::Left(source) => {
                    res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id)
                }
                Either::Right(source) => {
                    res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id)
                }
            }
        }
        res
    }
}

impl ChildBySource for EnumId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();

        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = EnumVariantId { parent: *self, local_id };
            res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id)
        }

        res
    }
}

impl ChildBySource for DefWithBodyId {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        let mut res = DynMap::default();
        let body = db.body(*self);
        body.defs.iter().copied().for_each(|item| add_module_def(db, &mut res, item));
        res
    }
}
<|endoftext|>


<commit_before>extern crate glib;
extern crate cairo;
extern crate libc;

use self::glib::translate::*;

use std::cell::Cell;
use std::ptr;

use aspect_ratio::*;
use drawing_ctx::RsvgDrawingCtx;
use drawing_ctx;
use handle::RsvgHandle;
use length::*;
use node::*;
use property_bag;
use property_bag::*;
use util::*;
use viewbox::*;

use self::cairo::MatrixTrait;

/***** NodeGroup *****/

struct NodeGroup ();

impl NodeGroup {
    fn new () -> NodeGroup {
        NodeGroup ()
    }
}

impl NodeTrait for NodeGroup {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        node.draw_children (draw_ctx, dominate);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeDefs *****/

struct NodeDefs ();

impl NodeDefs {
    fn new () -> NodeDefs {
        NodeDefs ()
    }
}

impl NodeTrait for NodeDefs {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
        // nothing
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeSwitch *****/

struct NodeSwitch ();

impl NodeSwitch {
    fn new () -> NodeSwitch {
        NodeSwitch ()
    }
}

impl NodeTrait for NodeSwitch {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);

        drawing_ctx::push_discrete_layer (draw_ctx);

        for child in &*node.children.borrow () {
            if drawing_ctx::state_get_cond_true (child.get_state ()) {
                let boxed_child = box_node (child.clone ());

                drawing_ctx::draw_node_from_stack (draw_ctx, boxed_child, 0);

                rsvg_node_unref (boxed_child);

                break;
            }
        }

        drawing_ctx::pop_discrete_layer (draw_ctx);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeSvg *****/

struct NodeSvg {
    preserve_aspect_ratio: Cell<AspectRatio>,
    x:                     Cell<RsvgLength>,
    y:                     Cell<RsvgLength>,
    w:                     Cell<RsvgLength>,
    h:                     Cell<RsvgLength>,
    vbox:                  Cell<RsvgViewBox>,
    atts:                  Cell<*mut RsvgPropertyBag>
}

impl NodeSvg {
    fn new () -> NodeSvg {
        NodeSvg {
            preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
            x:                     Cell::new (RsvgLength::parse ("0", LengthDir::Horizontal).unwrap ()),
            y:                     Cell::new (RsvgLength::parse ("0", LengthDir::Vertical).unwrap ()),
            w:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap ()),
            h:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap ()),
            vbox:                  Cell::new (RsvgViewBox::default ()),
            atts:                  Cell::new (ptr::null_mut ())
        }
    }
}

impl NodeTrait for NodeSvg {
    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);

        // x & y attributes have no effect on outermost svg
        // http://www.w3.org/TR/SVG/struct.html#SVGElement
        if node.get_parent ().is_some () {
            self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
            self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
        }

        self.w.set (property_bag::length_or_value (pbag, "width", LengthDir::Horizontal, "100%")?);
        self.h.set (property_bag::length_or_value (pbag, "height", LengthDir::Vertical, "100%")?);

        self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);

        // The "style" sub-element is not loaded yet here, so we need
        // to store other attributes to be applied later.
        self.atts.set (property_bag::dup (pbag));

        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        let nx = self.x.get ().normalize (draw_ctx);
        let ny = self.y.get ().normalize (draw_ctx);
        let nw = self.w.get ().normalize (draw_ctx);
        let nh = self.h.get ().normalize (draw_ctx);

        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);

        let state = drawing_ctx::get_current_state (draw_ctx);

        let affine_old = drawing_ctx::get_current_state_affine (draw_ctx);

        let vbox = self.vbox.get ();

        if vbox.active {
            // viewBox width==0 or height==0 disables rendering of the element
            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
            if double_equals (vbox.rect.width, 0.0) || double_equals (vbox.rect.height, 0.0) {
                return;
            }

            let (x, y, w, h) = self.preserve_aspect_ratio.get ().compute (vbox.rect.width, vbox.rect.height,
                                                                          nx, ny, nw, nh);

            let affine = cairo::Matrix::new (w / vbox.rect.width,
                                             0.0,
                                             0.0,
                                             h / vbox.rect.height,
                                             x - vbox.rect.x * w / vbox.rect.width,
                                             y - vbox.rect.y * h / vbox.rect.height);

            drawing_ctx::set_current_state_affine (draw_ctx, cairo::Matrix::multiply (&affine, &affine_old));

            drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
        } else {
            let mut affine = affine_old;
            affine.translate (nx, ny);

            drawing_ctx::set_current_state_affine (draw_ctx, affine);
            drawing_ctx::push_view_box (draw_ctx, nw, nh);
        }

        let affine_new = drawing_ctx::get_current_state_affine (draw_ctx);

        drawing_ctx::push_discrete_layer (draw_ctx);

        // Bounding box addition must be AFTER the discrete layer
        // push, which must be AFTER the transformation happens.

        if !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some () {
            drawing_ctx::set_current_state_affine (draw_ctx, affine_old);
            drawing_ctx::add_clipping_rect (draw_ctx, nx, ny, nw, nh);
            drawing_ctx::set_current_state_affine (draw_ctx, affine_new);
        }

        node.draw_children (draw_ctx, -1); // dominate==-1 so it won't reinherit or push a layer

        drawing_ctx::pop_discrete_layer (draw_ctx);
        drawing_ctx::pop_view_box (draw_ctx);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

impl Drop for NodeSvg {
    fn drop (&mut self) {
        let pbag = self.atts.get ();

        if !pbag.is_null () {
            property_bag::free (pbag);
        }
    }
}

/***** C Prototypes *****/

#[no_mangle]
pub extern fn rsvg_node_group_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Group,
                    raw_parent,
                    Box::new (NodeGroup::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_defs_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Defs,
                    raw_parent,
                    Box::new (NodeDefs::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_switch_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Switch,
                    raw_parent,
                    Box::new (NodeSwitch::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Svg,
                    raw_parent,
                    Box::new (NodeSvg::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_svg_get_size (raw_node: *const RsvgNode, out_width: *mut RsvgLength, out_height: *mut RsvgLength) {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    assert! (!out_width.is_null ());
    assert! (!out_height.is_null ());

    node.with_impl (|svg: &NodeSvg| {
        unsafe {
            *out_width  = svg.w.get ();
            *out_height = svg.h.get ();
        }
    });
}

#[no_mangle]
pub extern fn rsvg_node_svg_get_view_box (raw_node: *const RsvgNode) -> RsvgViewBox {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    let mut vbox = RsvgViewBox::default ();

    node.with_impl (|svg: &NodeSvg| {
        vbox = svg.vbox.get ();
    });

    vbox
}

extern "C" {
    fn rsvg_parse_style_attrs (handle: *const RsvgHandle,
                               node:   *const RsvgNode,
                               tag:    *const libc::c_char,
                               class:  *const libc::c_char,
                               id:     *const libc::c_char,
                               pbag:   *const RsvgPropertyBag);
}

#[no_mangle]
pub extern fn rsvg_node_svg_apply_atts (raw_node: *const RsvgNode, handle: *const RsvgHandle) {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    node.with_impl (|svg: &NodeSvg| {
        let pbag = svg.atts.get ();

        if !pbag.is_null () {
            let class = property_bag::lookup (pbag, "class");
            let id = property_bag::lookup (pbag, "id");

            unsafe { rsvg_parse_style_attrs (handle,
                                             raw_node,
                                             str::to_glib_none ("svg").0,
                                             class.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
                                             id.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
                                             pbag); }
        }
    });
}
<commit_msg>NodeSvg: Don't inline the computation of the SVG's affine<commit_after>extern crate glib;
extern crate cairo;
extern crate libc;

use self::glib::translate::*;

use std::cell::Cell;
use std::ptr;

use aspect_ratio::*;
use drawing_ctx::RsvgDrawingCtx;
use drawing_ctx;
use handle::RsvgHandle;
use length::*;
use node::*;
use property_bag;
use property_bag::*;
use util::*;
use viewbox::*;

use self::cairo::MatrixTrait;

/***** NodeGroup *****/

struct NodeGroup ();

impl NodeGroup {
    fn new () -> NodeGroup {
        NodeGroup ()
    }
}

impl NodeTrait for NodeGroup {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        node.draw_children (draw_ctx, dominate);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeDefs *****/

struct NodeDefs ();

impl NodeDefs {
    fn new () -> NodeDefs {
        NodeDefs ()
    }
}

impl NodeTrait for NodeDefs {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
        // nothing
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeSwitch *****/

struct NodeSwitch ();

impl NodeSwitch {
    fn new () -> NodeSwitch {
        NodeSwitch ()
    }
}

impl NodeTrait for NodeSwitch {
    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, _: *const RsvgPropertyBag) -> NodeResult {
        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);

        drawing_ctx::push_discrete_layer (draw_ctx);

        for child in &*node.children.borrow () {
            if drawing_ctx::state_get_cond_true (child.get_state ()) {
                let boxed_child = box_node (child.clone ());

                drawing_ctx::draw_node_from_stack (draw_ctx, boxed_child, 0);

                rsvg_node_unref (boxed_child);

                break;
            }
        }

        drawing_ctx::pop_discrete_layer (draw_ctx);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

/***** NodeSvg *****/

struct NodeSvg {
    preserve_aspect_ratio: Cell<AspectRatio>,
    x:                     Cell<RsvgLength>,
    y:                     Cell<RsvgLength>,
    w:                     Cell<RsvgLength>,
    h:                     Cell<RsvgLength>,
    vbox:                  Cell<RsvgViewBox>,
    atts:                  Cell<*mut RsvgPropertyBag>
}

impl NodeSvg {
    fn new () -> NodeSvg {
        NodeSvg {
            preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
            x:                     Cell::new (RsvgLength::parse ("0", LengthDir::Horizontal).unwrap ()),
            y:                     Cell::new (RsvgLength::parse ("0", LengthDir::Vertical).unwrap ()),
            w:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap ()),
            h:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap ()),
            vbox:                  Cell::new (RsvgViewBox::default ()),
            atts:                  Cell::new (ptr::null_mut ())
        }
    }
}

impl NodeTrait for NodeSvg {
    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);

        // x & y attributes have no effect on outermost svg
        // http://www.w3.org/TR/SVG/struct.html#SVGElement
        if node.get_parent ().is_some () {
            self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
            self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
        }

        self.w.set (property_bag::length_or_value (pbag, "width", LengthDir::Horizontal, "100%")?);
        self.h.set (property_bag::length_or_value (pbag, "height", LengthDir::Vertical, "100%")?);

        self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);

        // The "style" sub-element is not loaded yet here, so we need
        // to store other attributes to be applied later.
        self.atts.set (property_bag::dup (pbag));

        Ok (())
    }

    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
        let nx = self.x.get ().normalize (draw_ctx);
        let ny = self.y.get ().normalize (draw_ctx);
        let nw = self.w.get ().normalize (draw_ctx);
        let nh = self.h.get ().normalize (draw_ctx);

        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);

        let state = drawing_ctx::get_current_state (draw_ctx);

        let affine_old = drawing_ctx::get_current_state_affine (draw_ctx);

        let vbox = self.vbox.get ();

        if vbox.active {
            // viewBox width==0 or height==0 disables rendering of the element
            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
            if double_equals (vbox.rect.width, 0.0) || double_equals (vbox.rect.height, 0.0) {
                return;
            }

            let (x, y, w, h) = self.preserve_aspect_ratio.get ().compute (vbox.rect.width, vbox.rect.height,
                                                                          nx, ny, nw, nh);

            let mut affine = affine_old;
            affine.translate (x, y);
            affine.scale (w / vbox.rect.width, h / vbox.rect.height);
            affine.translate (-vbox.rect.x, -vbox.rect.y);
            drawing_ctx::set_current_state_affine (draw_ctx, affine);

            drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
        } else {
            let mut affine = affine_old;
            affine.translate (nx, ny);

            drawing_ctx::set_current_state_affine (draw_ctx, affine);
            drawing_ctx::push_view_box (draw_ctx, nw, nh);
        }

        let affine_new = drawing_ctx::get_current_state_affine (draw_ctx);

        drawing_ctx::push_discrete_layer (draw_ctx);

        // Bounding box addition must be AFTER the discrete layer
        // push, which must be AFTER the transformation happens.

        if !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some () {
            drawing_ctx::set_current_state_affine (draw_ctx, affine_old);
            drawing_ctx::add_clipping_rect (draw_ctx, nx, ny, nw, nh);
            drawing_ctx::set_current_state_affine (draw_ctx, affine_new);
        }

        node.draw_children (draw_ctx, -1); // dominate==-1 so it won't reinherit or push a layer

        drawing_ctx::pop_discrete_layer (draw_ctx);
        drawing_ctx::pop_view_box (draw_ctx);
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

impl Drop for NodeSvg {
    fn drop (&mut self) {
        let pbag = self.atts.get ();

        if !pbag.is_null () {
            property_bag::free (pbag);
        }
    }
}

/***** C Prototypes *****/

#[no_mangle]
pub extern fn rsvg_node_group_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Group,
                    raw_parent,
                    Box::new (NodeGroup::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_defs_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Defs,
                    raw_parent,
                    Box::new (NodeDefs::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_switch_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Switch,
                    raw_parent,
                    Box::new (NodeSwitch::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Svg,
                    raw_parent,
                    Box::new (NodeSvg::new ()))
}

#[no_mangle]
pub extern fn rsvg_node_svg_get_size (raw_node: *const RsvgNode, out_width: *mut RsvgLength, out_height: *mut RsvgLength) {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    assert! (!out_width.is_null ());
    assert! (!out_height.is_null ());

    node.with_impl (|svg: &NodeSvg| {
        unsafe {
            *out_width  = svg.w.get ();
            *out_height = svg.h.get ();
        }
    });
}

#[no_mangle]
pub extern fn rsvg_node_svg_get_view_box (raw_node: *const RsvgNode) -> RsvgViewBox {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    let mut vbox = RsvgViewBox::default ();

    node.with_impl (|svg: &NodeSvg| {
        vbox = svg.vbox.get ();
    });

    vbox
}

extern "C" {
    fn rsvg_parse_style_attrs (handle: *const RsvgHandle,
                               node:   *const RsvgNode,
                               tag:    *const libc::c_char,
                               class:  *const libc::c_char,
                               id:     *const libc::c_char,
                               pbag:   *const RsvgPropertyBag);
}

#[no_mangle]
pub extern fn rsvg_node_svg_apply_atts (raw_node: *const RsvgNode, handle: *const RsvgHandle) {
    assert! (!raw_node.is_null ());
    let node: &RsvgNode = unsafe { & *raw_node };

    node.with_impl (|svg: &NodeSvg| {
        let pbag = svg.atts.get ();

        if !pbag.is_null () {
            let class = property_bag::lookup (pbag, "class");
            let id = property_bag::lookup (pbag, "id");

            unsafe { rsvg_parse_style_attrs (handle,
                                             raw_node,
                                             str::to_glib_none ("svg").0,
                                             class.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
                                             id.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
                                             pbag); }
        }
    });
}
<|endoftext|>


<commit_before>///! Patch generation-application tests
///!
///! These integration tests check that, for various node types,
///! the `diff` and `apply` functions are consistent by doing round
///! trips, both ways, between two instances.
use pretty_assertions::assert_eq;
use proptest::collection::{size_range, vec};
use proptest::prelude::*;
use stencila::patches::{apply_new, diff};

mod strategies;
use strategies::{inline_content, Freedom};

macro_rules! assert_json_eq {
    ($expr1:expr, $expr2:expr) => {
        pretty_assertions::assert_eq!(
            serde_json::to_value(&$expr1).unwrap(),
            serde_json::to_value(&$expr2).unwrap()
        );
    };
}

proptest! {
    /// Any two strings including all unicode graphemes
    #[test]
    fn strings_any(
        a in any::<String>(),
        b in any::<String>()
    ) {
        let patch = diff(&a, &b);
        assert_eq!(apply_new(&a, &patch), b)
    }

    /// Zero to ten letters from a restricted range
    ///
    /// This test is useful because `strings_any` has a very low
    /// probability of generating `move` operations (because of the
    /// low probability of the same character appearing twice) and so
    /// was missing a bug associated with that operation.
    ///
    /// Move opertions have since been removed for strings but this
    /// test has been kept anyway.
    #[test]
    fn strings_restricted(
        a in "[a-e]{0,10}",
        b in "[a-e]{0,10}"
    ) {
        let patch = diff(&a, &b);
        assert_eq!(apply_new(&a, &patch), b)
    }

    // Any two inlines
    #[test]
    fn inlines(
        a in inline_content(Freedom::Low),
        b in inline_content(Freedom::Low)
    ) {
        let patch = diff(&a, &b);
        assert_json_eq!(apply_new(&a, &patch), b)
    }

    // Any two vectors of integers
    #[test]
    fn vec_integers(
        a in vec(0..10i64, size_range(0..10)),
        b in vec(0..10i64, size_range(0..10))
    ) {
        let patch = diff(&a, &b);
        assert_json_eq!(apply_new(&a, &patch), b)
    }
}
<commit_msg>test(Patches): Include proptest cases<commit_after>///! Patch generation-application tests
///!
///! These integration tests check that, for various node types,
///! the `diff` and `apply` functions are consistent by doing round
///! trips, both ways, between two instances.
use pretty_assertions::assert_eq;
use proptest::collection::{size_range, vec};
use proptest::prelude::*;
use stencila::patches::{apply_new, diff};

mod strategies;
use strategies::{inline_content, Freedom};

macro_rules! assert_json_eq {
    ($expr1:expr, $expr2:expr) => {
        pretty_assertions::assert_eq!(
            serde_json::to_value(&$expr1).unwrap(),
            serde_json::to_value(&$expr2).unwrap()
        );
    };
}

proptest! {
    // Higher number of cases than the default because some patches can fail
    // on rare corner cases (in particular `Move` operations).
    #![proptest_config(ProptestConfig::with_cases(1000))]

    /// Any two strings including all unicode graphemes
    #[test]
    fn strings_any(
        a in any::<String>(),
        b in any::<String>()
    ) {
        let patch = diff(&a, &b);
        assert_eq!(apply_new(&a, &patch), b)
    }

    /// Zero to ten letters from a restricted range
    ///
    /// This test is useful because `strings_any` has a very low
    /// probability of generating `Move` operations (because of the
    /// low probability of the same character appearing twice) and so
    /// was missing a bug associated with that operation. Move operations
    /// have since been removed for strings but this test has been kept anyway.
    #[test]
    fn strings_restricted(
        a in "[a-e]{0,10}",
        b in "[a-e]{0,10}"
    ) {
        let patch = diff(&a, &b);
        assert_eq!(apply_new(&a, &patch), b)
    }

    // Any two inlines
    #[test]
    fn inlines(
        a in inline_content(Freedom::Low),
        b in inline_content(Freedom::Low)
    ) {
        let patch = diff(&a, &b);
        assert_json_eq!(apply_new(&a, &patch), b)
    }

    // Any two vectors of integers
    #[test]
    fn vec_integers(
        a in vec(0..10i64, size_range(0..10)),
        b in vec(0..10i64, size_range(0..10))
    ) {
        let patch = diff(&a, &b);
        assert_json_eq!(apply_new(&a, &patch), b)
    }
}
<|endoftext|>