table 0.4.0

A specialized map for storing values of varying types.
Documentation
// Copyright (C) 2018  Project Tsukurou!
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::borrow::Cow;

/// Defines the types that can be used to index into a table.
///
/// It is necessary to have a type that is separate from `Value` because some
/// of the `Value` variants are not hashable, most notably:
///
/// - `f64` does not implement `Eq` or `Hash` for some pretty complex reasons.
/// Comparing floating-point values for equality is non-trivial due to some
/// precision issues, also making it hard to create a stable hash function.
///
///
/// - `Table` does not implement `Hash` because it is an unordered collection,
/// meaning it can't reliably or efficiently hash all of its elements in the
/// same order every time.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Key<'a> {

    /// A boolean type with two states, `true` and `false`.
    Bool(bool),

    /// A floating-point type with 64-bit precision.
    I64(i64),

    /// A slice of bytes wrapped with a clone-on-write container.
    Bytes(Box<Cow<'a, [u8]>>),

    /// A UTF-8 string.
    String(Box<Cow<'a, str>>),
}

convert!(enum Key<'a>, variant Key::Bool: type bool);
convert!(enum Key<'a>, variant Key::I64: type i64);
convert!(enum Key<'a>, variant Key::Bytes: type Box<Cow<'a, [u8]>>);
convert!(enum Key<'a>, variant Key::String: type Box<Cow<'a, str>>);

convert!(enum Key<'a>, type i64: from i8, i16, i32, u8, u16, u32);
convert!(enum Key<'a>, type i64: from_as u64, usize, isize);
convert!(enum Key<'a>, type Box<Cow<'a, [u8]>>: from Cow<'a, [u8]>);
convert!(enum Key<'a>, type Box<Cow<'a, [u8]>>: ref Cow<'a, [u8]>);
convert!(enum Key<'a>, type Box<Cow<'a, str>>: from Cow<'a, str>);
convert!(enum Key<'a>, type Box<Cow<'a, str>>: ref Cow<'a, str>);
convert!(enum Key<'a>: cow [u8], Vec<u8>);
convert!(enum Key<'a>: cow str, String);

impl<'a> AsRef<Key<'a>> for Key<'a> {
    fn as_ref(&self) -> &Key<'a> {
        self
    }
}

impl<'a> AsMut<Key<'a>> for Key<'a> {
    fn as_mut(&mut self) -> &mut Key<'a> {
        self
    }
}