use num::bigint::BigInt;
use num::traits::cast::ToPrimitive;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::convert::From;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::io;
use std::ops::Index;
use std::ops::IndexMut;
use std::string::String;
use std::sync::Arc;
use std::vec::Vec;

pub use std::collections::BTreeSet as Set;
pub use std::collections::BTreeMap as Map;

use super::DebugDomainEncode;
use super::FromStrDomainParse;
use super::IOValueDomainCodec;
use super::TextWriter;
use super::Writer;
use super::signed_integer::SignedInteger;
use super::text;
use crate::error::{Error, ExpectedKind, Received};

pub trait Domain: Sized + Debug + Eq + Hash + Ord {
    fn debug_encode<W: Writer>(&self, w: &mut W) -> io::Result<()> {
        w.write_string(&format!("{:?}", self))
    }
}

pub trait Embeddable: Domain + Clone {}
impl<T> Embeddable for T where T: Domain + Clone {}

impl<D: Domain> Domain for Arc<D> {
    fn debug_encode<W: Writer>(&self, w: &mut W) -> io::Result<()> {
        self.as_ref().debug_encode(w)
    }
}

pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord {
    type Embedded: Embeddable;

    #[inline(always)]
    fn new<V>(v: V) -> Self where Value<Self>: From<V> {
        Value::from(v).wrap()
    }

    #[inline(always)]
    fn domain<E>(e: E) -> Self where Self::Embedded: From<E> {
        Value::Embedded(e.into()).wrap()
    }

    #[inline(always)]
    fn symbol(n: &str) -> Self {
        Value::symbol(n).wrap()
    }

    #[inline(always)]
    fn bytestring<'a, V: Into<Cow<'a, [u8]>>>(v: V) -> Self {
        Value::bytestring(v).wrap()
    }

    fn wrap(anns: Annotations<Self>, v: Value<Self>) -> Self;

    fn annotations(&self) -> &Annotations<Self>;
    fn value(&self) -> &Value<Self>;
    fn pieces(self) -> (Annotations<Self>, Value<Self>);
    fn value_owned(self) -> Value<Self>;

    #[inline(always)]
    fn value_class(&self) -> ValueClass {
        self.value().value_class()
    }

    fn debug_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        for ann in self.annotations().slice() {
            write!(f, "@{:?} ", ann)?;
        }
        self.value().fmt(f)
    }

    fn strip_annotations<M: NestedValue<Embedded = Self::Embedded>>(&self) -> M {
        M::wrap(Annotations::empty(), self.value().strip_annotations())
    }

    fn copy_via<M: NestedValue, F, Err>(&self, f: &mut F) -> Result<M, Err>
    where
        F: FnMut(&Self::Embedded) -> Result<Value<M>, Err>
    {
        Ok(M::wrap(self.annotations().copy_via(f)?, self.value().copy_via(f)?))
    }

    fn foreach_embedded<F, Err>(&self, f: &mut F) -> Result<(), Err>
    where
        F: FnMut(&Self::Embedded) -> Result<(), Err>
    {
        match &self.annotations().0 {
            None => (),
            Some(vs) => for v in vs.iter() { v.foreach_embedded(f)? },
        }
        self.value().foreach_embedded(f)
    }
}

/// The `Value`s from the specification.
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Value<N: NestedValue> {
    Boolean(bool),
    Float(Float),
    Double(Double),
    SignedInteger(SignedInteger),
    String(String),
    ByteString(Vec<u8>),
    Symbol(String),
    Record(Record<N>),
    Sequence(Vec<N>),
    Set(Set<N>),
    Dictionary(Map<N, N>),
    Embedded(N::Embedded),
}

/// The kinds of `Value` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ValueClass {
    Atomic(AtomClass),
    Compound(CompoundClass),
    Embedded,
}

/// The kinds of `Atom` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum AtomClass {
    Boolean,
    Float,
    Double,
    SignedInteger,
    String,
    ByteString,
    Symbol,
}

/// The kinds of `Compound` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum CompoundClass {
    Record,
    Sequence,
    Set,
    Dictionary,
}

/// Single-precision IEEE 754 Value
#[derive(Clone, Copy, Debug)]
pub struct Float(pub f32);

/// Double-precision IEEE 754 Value
#[derive(Clone, Copy, Debug)]
pub struct Double(pub f64);

/// A Record `Value` -- INVARIANT: length always non-zero
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Record<N>(pub Vec<N>);

impl<N> Record<N> {
    #[inline(always)]
    pub fn label(&self) -> &N {
        &self.0[0]
    }

    #[inline(always)]
    pub fn label_mut(&mut self) -> &mut N {
        &mut self.0[0]
    }

    #[inline(always)]
    pub fn arity(&self) -> usize {
        self.0.len() - 1
    }

    #[inline(always)]
    pub fn fields(&self) -> &[N] {
        &self.0[1..]
    }

    #[inline(always)]
    pub fn fields_mut(&mut self) -> &mut [N] {
        &mut self.0[1..]
    }

    #[inline(always)]
    pub fn fields_vec(&self) -> &Vec<N> {
        &self.0
    }

    #[inline(always)]
    pub fn fields_vec_mut(&mut self) -> &mut Vec<N> {
        &mut self.0
    }

    #[inline(always)]
    pub fn finish(self) -> Value<N> where N: NestedValue {
        Value::Record(self)
    }
}

impl From<f32> for Float {
    fn from(v: f32) -> Self {
        Float(v)
    }
}

impl From<Float> for f32 {
    fn from(v: Float) -> Self {
        v.0
    }
}

impl Hash for Float {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.to_bits().hash(state);
    }
}

impl PartialEq for Float {
    fn eq(&self, other: &Self) -> bool {
        self.0.to_bits() == other.0.to_bits()
    }
}

impl Ord for Float {
    fn cmp(&self, other: &Self) -> Ordering {
        let mut a: u32 = self.0.to_bits();
        let mut b: u32 = other.0.to_bits();
        if a & 0x8000_0000 != 0 { a ^= 0x7fff_ffff; }
        if b & 0x8000_0000 != 0 { b ^= 0x7fff_ffff; }
        (a as i32).cmp(&(b as i32))
    }
}

impl PartialOrd for Float {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for Float {}

impl From<f64> for Double {
    fn from(v: f64) -> Self {
        Double(v)
    }
}

impl From<Double> for f64 {
    fn from(v: Double) -> Self {
        v.0
    }
}

impl Hash for Double {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.to_bits().hash(state);
    }
}

impl PartialEq for Double {
    fn eq(&self, other: &Self) -> bool {
        self.0.to_bits() == other.0.to_bits()
    }
}

impl Ord for Double {
    fn cmp(&self, other: &Self) -> Ordering {
        let mut a: u64 = self.0.to_bits();
        let mut b: u64 = other.0.to_bits();
        if a & 0x8000_0000_0000_0000 != 0 { a ^= 0x7fff_ffff_ffff_ffff; }
        if b & 0x8000_0000_0000_0000 != 0 { b ^= 0x7fff_ffff_ffff_ffff; }
        (a as i64).cmp(&(b as i64))
    }
}

impl PartialOrd for Double {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for Double {}

impl<N: NestedValue> From<bool> for Value<N> { fn from(v: bool) -> Self { Value::Boolean(v) } }
impl<N: NestedValue> From<&bool> for Value<N> { fn from(v: &bool) -> Self { Value::Boolean(*v) } }

impl<N: NestedValue> From<f32> for Value<N> { fn from(v: f32) -> Self { Value::Float(Float::from(v)) } }
impl<N: NestedValue> From<&f32> for Value<N> { fn from(v: &f32) -> Self { Value::Float(Float::from(*v)) } }
impl<N: NestedValue> From<&Float> for Value<N> { fn from(v: &Float) -> Self { Value::Float(v.clone()) } }
impl<N: NestedValue> From<f64> for Value<N> { fn from(v: f64) -> Self { Value::Double(Double::from(v)) } }
impl<N: NestedValue> From<&f64> for Value<N> { fn from(v: &f64) -> Self { Value::Double(Double::from(*v)) } }
impl<N: NestedValue> From<&Double> for Value<N> { fn from(v: &Double) -> Self { Value::Double(v.clone()) } }

impl<N: NestedValue> From<u8> for Value<N> { fn from(v: u8) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<i8> for Value<N> { fn from(v: i8) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<u16> for Value<N> { fn from(v: u16) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<i16> for Value<N> { fn from(v: i16) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<u32> for Value<N> { fn from(v: u32) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<i32> for Value<N> { fn from(v: i32) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<u64> for Value<N> { fn from(v: u64) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<i64> for Value<N> { fn from(v: i64) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue> From<usize> for Value<N> { fn from(v: usize) -> Self { Value::from(v as u128) } }
impl<N: NestedValue> From<isize> for Value<N> { fn from(v: isize) -> Self { Value::from(v as i128) } }
impl<N: NestedValue> From<u128> for Value<N> { fn from(v: u128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
impl<N: NestedValue> From<i128> for Value<N> { fn from(v: i128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
impl<N: NestedValue> From<&BigInt> for Value<N> { fn from(v: &BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) } }
impl<N: NestedValue> From<BigInt> for Value<N> { fn from(v: BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Owned(v))) } }
impl<N: NestedValue> From<&SignedInteger> for Value<N> { fn from(v: &SignedInteger) -> Self { Value::SignedInteger(v.clone()) } }

impl<N: NestedValue> From<&str> for Value<N> { fn from(v: &str) -> Self { Value::String(String::from(v)) } }
impl<N: NestedValue> From<String> for Value<N> { fn from(v: String) -> Self { Value::String(v) } }
impl<N: NestedValue> From<&String> for Value<N> { fn from(v: &String) -> Self { Value::String(v.to_owned()) } }

impl<N: NestedValue> From<&[u8]> for Value<N> { fn from(v: &[u8]) -> Self { Value::ByteString(Vec::from(v)) } }
// impl<N: NestedValue> From<Vec<u8>> for Value<N> { fn from(v: Vec<u8>) -> Self { Value::ByteString(v) } }

impl<N: NestedValue> From<Vec<N>> for Value<N> { fn from(v: Vec<N>) -> Self { Value::Sequence(v) } }
impl<N: NestedValue> From<Set<N>> for Value<N> { fn from(v: Set<N>) -> Self { Value::Set(v) } }
impl<N: NestedValue> From<Map<N, N>> for Value<N> { fn from(v: Map<N, N>) -> Self { Value::Dictionary(v) } }

impl<N: NestedValue> Debug for Value<N> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        TextWriter::fmt_value(f, &mut DebugDomainEncode, self).map_err(|_| std::fmt::Error)
    }
}

impl<Err: Into<io::Error>, D: Embeddable + std::str::FromStr<Err = Err>, N: NestedValue<Embedded = D>>
    std::str::FromStr for Value<N>
{
    type Err = io::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(text::from_str::<N, _>(s, FromStrDomainParse)?.value_owned())
    }
}

//---------------------------------------------------------------------------

impl<N: NestedValue> Value<N> {
    pub fn wrap(self) -> N {
        N::wrap(Annotations::empty(), self)
    }

    fn value_class(&self) -> ValueClass {
        match self {
            Value::Boolean(_) => ValueClass::Atomic(AtomClass::Boolean),
            Value::Float(_) => ValueClass::Atomic(AtomClass::Float),
            Value::Double(_) => ValueClass::Atomic(AtomClass::Double),
            Value::SignedInteger(_) => ValueClass::Atomic(AtomClass::SignedInteger),
            Value::String(_) => ValueClass::Atomic(AtomClass::String),
            Value::ByteString(_) => ValueClass::Atomic(AtomClass::ByteString),
            Value::Symbol(_) => ValueClass::Atomic(AtomClass::Symbol),
            Value::Record(_) => ValueClass::Compound(CompoundClass::Record),
            Value::Sequence(_) => ValueClass::Compound(CompoundClass::Sequence),
            Value::Set(_) => ValueClass::Compound(CompoundClass::Set),
            Value::Dictionary(_) => ValueClass::Compound(CompoundClass::Dictionary),
            Value::Embedded(_) => ValueClass::Embedded,
        }
    }

    pub fn children(&self) -> Vec<N> {
        match self {
            Value::Boolean(_) |
            Value::Float(_) |
            Value::Double(_) |
            Value::SignedInteger(_) |
            Value::String(_) |
            Value::ByteString(_) |
            Value::Symbol(_) |
            Value::Embedded(_) => vec![],

            Value::Record(r) => r.fields().to_vec(),
            Value::Sequence(vs) => vs.clone(),
            Value::Set(s) => s.iter().cloned().collect(),
            Value::Dictionary(d) => d.values().cloned().collect(),
        }
    }

    fn expected(&self, k: ExpectedKind) -> Error {
        Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", self.clone().wrap())))
    }

    #[inline(always)]
    pub fn is_boolean(&self) -> bool {
        self.as_boolean().is_some()
    }

    #[inline(always)]
    pub fn as_boolean(&self) -> Option<bool> {
        if let Value::Boolean(b) = self {
            Some(*b)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_boolean_mut(&mut self) -> Option<&mut bool> {
        if let Value::Boolean(b) = self {
            Some(b)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_boolean(&self) -> Result<bool, Error> {
        self.as_boolean().ok_or_else(|| self.expected(ExpectedKind::Boolean))
    }

    #[inline(always)]
    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    #[inline(always)]
    pub fn as_float(&self) -> Option<&Float> {
        if let Value::Float(f) = self {
            Some(f)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_float_mut(&mut self) -> Option<&mut Float> {
        if let Value::Float(f) = self {
            Some(f)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_float(&self) -> Result<&Float, Error> {
        self.as_float().ok_or_else(|| self.expected(ExpectedKind::Float))
    }

    #[inline(always)]
    pub fn is_f32(&self) -> bool {
        self.is_float()
    }

    #[inline(always)]
    pub fn as_f32(&self) -> Option<f32> {
        self.as_float().map(|f| f.0)
    }

    #[inline(always)]
    pub fn as_f32_mut(&mut self) -> Option<&mut f32> {
        self.as_float_mut().map(|f| &mut f.0)
    }

    #[inline(always)]
    pub fn to_f32(&self) -> Result<f32, Error> {
        self.to_float().map(|f| f.0)
    }

    #[inline(always)]
    pub fn is_double(&self) -> bool {
        self.as_double().is_some()
    }

    #[inline(always)]
    pub fn as_double(&self) -> Option<&Double> {
        if let Value::Double(f) = self {
            Some(f)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_double_mut(&mut self) -> Option<&mut Double> {
        if let Value::Double(f) = self {
            Some(f)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_double(&self) -> Result<&Double, Error> {
        self.as_double().ok_or_else(|| self.expected(ExpectedKind::Double))
    }

    #[inline(always)]
    pub fn is_f64(&self) -> bool {
        self.is_double()
    }

    #[inline(always)]
    pub fn as_f64(&self) -> Option<f64> {
        self.as_double().map(|f| f.0)
    }

    #[inline(always)]
    pub fn as_f64_mut(&mut self) -> Option<&mut f64> {
        self.as_double_mut().map(|f| &mut f.0)
    }

    #[inline(always)]
    pub fn to_f64(&self) -> Result<f64, Error> {
        self.to_double().map(|f| f.0)
    }

    #[inline(always)]
    pub fn is_signedinteger(&self) -> bool {
        self.as_signedinteger().is_some()
    }

    #[inline(always)]
    pub fn as_signedinteger(&self) -> Option<&SignedInteger> {
        if let Value::SignedInteger(n) = self {
            Some(n)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_signedinteger_mut(&mut self) -> Option<&mut SignedInteger> {
        if let Value::SignedInteger(n) = self {
            Some(n)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_signedinteger(&self) -> Result<&SignedInteger, Error> {
        self.as_signedinteger().ok_or_else(|| self.expected(ExpectedKind::SignedInteger))
    }

    #[inline(always)]
    pub fn is_i(&self) -> bool {
        self.as_i().is_some()
    }

    #[inline(always)]
    pub fn as_i(&self) -> Option<i128> {
        self.as_signedinteger().and_then(|n| n.try_into().ok())
    }

    #[inline(always)]
    pub fn to_i(&self) -> Result<i128, Error> {
        self.as_i().ok_or_else(|| self.expected(ExpectedKind::SignedIntegerI128))
    }

    #[inline(always)]
    pub fn is_u(&self) -> bool {
        self.as_u().is_some()
    }

    #[inline(always)]
    pub fn as_u(&self) -> Option<u128> {
        self.as_signedinteger().and_then(|n| n.try_into().ok())
    }

    #[inline(always)]
    pub fn to_u(&self) -> Result<u128, Error> {
        self.as_u().ok_or_else(|| self.expected(ExpectedKind::SignedIntegerU128))
    }

    #[inline(always)]
    pub fn as_u8(&self) -> Option<u8> { self.as_u().and_then(|i| i.to_u8()) }
    #[inline(always)]
    pub fn as_i8(&self) -> Option<i8> { self.as_i().and_then(|i| i.to_i8()) }
    #[inline(always)]
    pub fn as_u16(&self) -> Option<u16> { self.as_u().and_then(|i| i.to_u16()) }
    #[inline(always)]
    pub fn as_i16(&self) -> Option<i16> { self.as_i().and_then(|i| i.to_i16()) }
    #[inline(always)]
    pub fn as_u32(&self) -> Option<u32> { self.as_u().and_then(|i| i.to_u32()) }
    #[inline(always)]
    pub fn as_i32(&self) -> Option<i32> { self.as_i().and_then(|i| i.to_i32()) }
    #[inline(always)]
    pub fn as_u64(&self) -> Option<u64> { self.as_u().and_then(|i| i.to_u64()) }
    #[inline(always)]
    pub fn as_i64(&self) -> Option<i64> { self.as_i().and_then(|i| i.to_i64()) }
    #[inline(always)]
    pub fn as_u128(&self) -> Option<u128> { self.as_u().and_then(|i| i.to_u128()) }
    #[inline(always)]
    pub fn as_i128(&self) -> Option<i128> { self.as_i().and_then(|i| i.to_i128()) }
    #[inline(always)]
    pub fn as_usize(&self) -> Option<usize> { self.as_u().and_then(|i| i.to_usize()) }
    #[inline(always)]
    pub fn as_isize(&self) -> Option<isize> { self.as_i().and_then(|i| i.to_isize()) }

    #[inline(always)]
    pub fn to_i8(&self) -> Result<i8, Error> {
        match self.as_i() {
            Some(i) => i.to_i8().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_u8(&self) -> Result<u8, Error> {
        match self.as_u() {
            Some(i) => i.to_u8().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_i16(&self) -> Result<i16, Error> {
        match self.as_i() {
            Some(i) => i.to_i16().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_u16(&self) -> Result<u16, Error> {
        match self.as_u() {
            Some(i) => i.to_u16().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_i32(&self) -> Result<i32, Error> {
        match self.as_i() {
            Some(i) => i.to_i32().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_u32(&self) -> Result<u32, Error> {
        match self.as_u() {
            Some(i) => i.to_u32().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_i64(&self) -> Result<i64, Error> {
        match self.as_i() {
            Some(i) => i.to_i64().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_u64(&self) -> Result<u64, Error> {
        match self.as_u() {
            Some(i) => i.to_u64().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_i128(&self) -> Result<i128, Error> {
        match self.as_i() {
            Some(i) => i.to_i128().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_u128(&self) -> Result<u128, Error> {
        match self.as_u() {
            Some(i) => i.to_u128().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_isize(&self) -> Result<isize, Error> {
        match self.as_i() {
            Some(i) => i.to_isize().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_usize(&self) -> Result<usize, Error> {
        match self.as_u() {
            Some(i) => i.to_usize().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
            None => Err(self.expected(ExpectedKind::SignedInteger)),
        }
    }

    #[inline(always)]
    pub fn to_char(&self) -> Result<char, Error> {
        let fs = self.to_simple_record("UnicodeScalar", Some(1))?;
        let c = fs[0].value().to_u32()?;
        char::try_from(c).map_err(|_| Error::InvalidUnicodeScalar(c))
    }

    #[inline(always)]
    pub fn is_string(&self) -> bool {
        self.as_string().is_some()
    }

    #[inline(always)]
    pub fn as_string(&self) -> Option<&String> {
        if let Value::String(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_string_mut(&mut self) -> Option<&mut String> {
        if let Value::String(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_string(self) -> Option<String> {
        match self {
            Value::String(s) => Some(s),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn to_string(&self) -> Result<&String, Error> {
        self.as_string().ok_or_else(|| self.expected(ExpectedKind::String))
    }

    #[inline(always)]
    pub fn bytestring<'a, V: Into<Cow<'a, [u8]>>>(v: V) -> Self {
        Value::ByteString(v.into().into_owned())
    }

    #[inline(always)]
    pub fn is_bytestring(&self) -> bool {
        self.as_bytestring().is_some()
    }

    #[inline(always)]
    pub fn as_bytestring(&self) -> Option<&Vec<u8>> {
        if let Value::ByteString(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_bytestring_mut(&mut self) -> Option<&mut Vec<u8>> {
        if let Value::ByteString(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_bytestring(self) -> Option<Vec<u8>> {
        match self {
            Value::ByteString(bs) => Some(bs),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn to_bytestring(&self) -> Result<&Vec<u8>, Error> {
        self.as_bytestring().ok_or_else(|| self.expected(ExpectedKind::ByteString))
    }

    #[inline(always)]
    pub fn symbol(s: &str) -> Value<N> {
        Value::Symbol(s.to_string())
    }

    #[inline(always)]
    pub fn is_symbol(&self) -> bool {
        self.as_symbol().is_some()
    }

    #[inline(always)]
    pub fn as_symbol(&self) -> Option<&String> {
        if let Value::Symbol(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn as_symbol_mut(&mut self) -> Option<&mut String> {
        if let Value::Symbol(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_symbol(self) -> Option<String> {
        match self {
            Value::Symbol(s) => Some(s),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn to_symbol(&self) -> Result<&String, Error> {
        self.as_symbol().ok_or_else(|| self.expected(ExpectedKind::Symbol))
    }

    #[inline(always)]
    pub fn record(label: N, expected_arity: usize) -> Record<N> {
        let mut v = Vec::with_capacity(expected_arity + 1);
        v.push(label);
        Record(v)
    }

    #[inline(always)]
    pub fn is_record(&self) -> bool {
        matches!(*self, Value::Record(_))
    }

    #[inline(always)]
    pub fn as_record(&self, arity: Option<usize>) -> Option<&Record<N>> {
        if let Value::Record(r) = self {
            match arity {
                Some(expected) if r.arity() == expected => Some(r),
                Some(_other) => None,
                None => Some(r)
            }
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_record(self) -> Option<Record<N>> {
        match self {
            Value::Record(r) => Some(r),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn as_record_mut(&mut self, arity: Option<usize>) -> Option<&mut Record<N>> {
        if let Value::Record(r) = self {
            match arity {
                Some(expected) if r.arity() == expected => Some(r),
                Some(_other) => None,
                None => Some(r)
            }
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_record(&self, arity: Option<usize>) -> Result<&Record<N>, Error> {
        self.as_record(arity).ok_or_else(|| self.expected(ExpectedKind::Record(arity)))
    }

    #[inline(always)]
    pub fn simple_record(label: &str, expected_arity: usize) -> Record<N> {
        Self::record(N::symbol(label), expected_arity)
    }

    #[inline(always)]
    pub fn simple_record0(label: &str) -> Value<N> {
        Self::simple_record(label, 0).finish()
    }

    #[inline(always)]
    pub fn simple_record1(label: &str, field: N) -> Value<N> {
        let mut r = Self::simple_record(label, 1);
        r.fields_vec_mut().push(field);
        r.finish()
    }

    #[inline(always)]
    pub fn is_simple_record(&self, label: &str, arity: Option<usize>) -> bool {
        self.as_simple_record(label, arity).is_some()
    }

    #[inline(always)]
    pub fn as_simple_record(&self, label: &str, arity: Option<usize>) -> Option<&[N]> {
        self.as_record(arity).and_then(|r| {
            match r.label().value() {
                Value::Symbol(s) if s == label => Some(r.fields()),
                _ => None
            }
        })
    }

    #[inline(always)]
    pub fn to_simple_record(&self, label: &str, arity: Option<usize>) ->
        Result<&[N], Error>
    {
        self.as_simple_record(label, arity)
            .ok_or_else(|| self.expected(ExpectedKind::SimpleRecord(label.to_owned(), arity)))
    }

    #[inline(always)]
    pub fn to_option(&self) -> Result<Option<&N>, Error> {
        match self.as_simple_record("None", Some(0)) {
            Some(_fs) => Ok(None),
            None => match self.as_simple_record("Some", Some(1)) {
                Some(fs) => Ok(Some(&fs[0])),
                None => Err(self.expected(ExpectedKind::Option))
            }
        }
    }

    #[inline(always)]
    pub fn is_sequence(&self) -> bool {
        self.as_sequence().is_some()
    }

    #[inline(always)]
    pub fn as_sequence(&self) -> Option<&Vec<N>> {
        if let Value::Sequence(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_sequence(self) -> Option<Vec<N>> {
        match self {
            Value::Sequence(s) => Some(s),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn as_sequence_mut(&mut self) -> Option<&mut Vec<N>> {
        if let Value::Sequence(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_sequence(&self) -> Result<&Vec<N>, Error> {
        self.as_sequence().ok_or_else(|| self.expected(ExpectedKind::Sequence))
    }

    #[inline(always)]
    pub fn is_set(&self) -> bool {
        self.as_set().is_some()
    }

    #[inline(always)]
    pub fn as_set(&self) -> Option<&Set<N>> {
        if let Value::Set(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_set(self) -> Option<Set<N>> {
        match self {
            Value::Set(s) => Some(s),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn as_set_mut(&mut self) -> Option<&mut Set<N>> {
        if let Value::Set(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_set(&self) -> Result<&Set<N>, Error> {
        self.as_set().ok_or_else(|| self.expected(ExpectedKind::Set))
    }

    #[inline(always)]
    pub fn is_dictionary(&self) -> bool {
        self.as_dictionary().is_some()
    }

    #[inline(always)]
    pub fn as_dictionary(&self) -> Option<&Map<N, N>> {
        if let Value::Dictionary(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn into_dictionary(self) -> Option<Map<N, N>> {
        match self {
            Value::Dictionary(s) => Some(s),
            _ => None,
        }
    }

    #[inline(always)]
    pub fn as_dictionary_mut(&mut self) -> Option<&mut Map<N, N>> {
        if let Value::Dictionary(s) = self {
            Some(s)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_dictionary(&self) -> Result<&Map<N, N>, Error> {
        self.as_dictionary().ok_or_else(|| self.expected(ExpectedKind::Dictionary))
    }

    #[inline(always)]
    pub fn is_embedded(&self) -> bool {
        self.as_embedded().is_some()
    }

    #[inline(always)]
    pub fn as_embedded(&self) -> Option<&N::Embedded> {
        if let Value::Embedded(d) = self {
            Some(d)
        } else {
            None
        }
    }

    #[inline(always)]
    pub fn to_embedded(&self) -> Result<&N::Embedded, Error> {
        self.as_embedded().ok_or_else(|| self.expected(ExpectedKind::Embedded))
    }

    pub fn strip_annotations<M: NestedValue<Embedded = N::Embedded>>(&self) -> Value<M> {
        match self {
            Value::Boolean(b) => Value::Boolean(*b),
            Value::Float(f) => Value::Float(f.clone()),
            Value::Double(d) => Value::Double(d.clone()),
            Value::SignedInteger(n) => Value::SignedInteger(n.clone()),
            Value::String(s) => Value::String(s.clone()),
            Value::ByteString(v) => Value::ByteString(v.clone()),
            Value::Symbol(v) => Value::Symbol(v.clone()),
            Value::Record(r) => Value::Record(Record(r.fields_vec().iter().map(
                |a| a.strip_annotations()).collect())),
            Value::Sequence(v) => Value::Sequence(v.iter().map(
                |a| a.strip_annotations()).collect()),
            Value::Set(v) => Value::Set(v.iter().map(
                |a| a.strip_annotations()).collect()),
            Value::Dictionary(v) => Value::Dictionary(v.iter().map(
                |(a,b)| (a.strip_annotations(), b.strip_annotations())).collect()),
            Value::Embedded(d) => Value::Embedded(d.clone()),
        }
    }

    pub fn copy_via<M: NestedValue, F, Err>(&self, f: &mut F) -> Result<Value<M>, Err>
    where
        F: FnMut(&N::Embedded) -> Result<Value<M>, Err>
    {
        Ok(match self {
            Value::Boolean(b) => Value::Boolean(*b),
            Value::Float(f) => Value::Float(f.clone()),
            Value::Double(d) => Value::Double(d.clone()),
            Value::SignedInteger(n) => Value::SignedInteger(n.clone()),
            Value::String(s) => Value::String(s.clone()),
            Value::ByteString(v) => Value::ByteString(v.clone()),
            Value::Symbol(v) => Value::Symbol(v.clone()),
            Value::Record(r) =>
                Value::Record(Record(r.fields_vec().iter().map(|a| a.copy_via(f))
                                     .collect::<Result<Vec<_>, _>>()?)),
            Value::Sequence(v) => Value::Sequence(v.iter().map(|a| a.copy_via(f))
                                                      .collect::<Result<Vec<_>, _>>()?),
            Value::Set(v) => Value::Set(v.iter().map(|a| a.copy_via(f))
                                            .collect::<Result<Set<_>, _>>()?),
            Value::Dictionary(v) =>
                Value::Dictionary(v.iter().map(|(a,b)| Ok((a.copy_via(f)?, b.copy_via(f)?)))
                                  .collect::<Result<Map<_, _>, _>>()?),
            Value::Embedded(d) => f(d)?,
        })
    }

    pub fn foreach_embedded<F, Err>(&self, f: &mut F) -> Result<(), Err>
    where
        F: FnMut(&N::Embedded) -> Result<(), Err>
    {
        match self {
            Value::Boolean(_) |
            Value::Float(_) |
            Value::Double(_) |
            Value::SignedInteger(_) |
            Value::String(_) |
            Value::ByteString(_) |
            Value::Symbol(_) => Ok(()),
            Value::Record(r) => Ok(for v in r.fields_vec() { v.foreach_embedded(f)? }),
            Value::Sequence(vs) => Ok(for v in vs { v.foreach_embedded(f)? }),
            Value::Set(vs) => Ok(for v in vs { v.foreach_embedded(f)? }),
            Value::Dictionary(d) => Ok(for (k, v) in d {
                k.foreach_embedded(f)?;
                v.foreach_embedded(f)?;
            }),
            Value::Embedded(d) => f(d),
        }
    }
}

impl<N: NestedValue> Index<usize> for Value<N> {
    type Output = N;

    #[inline(always)]
    fn index(&self, i: usize) -> &Self::Output {
        &self.as_sequence().unwrap()[i]
    }
}

impl<N: NestedValue> IndexMut<usize> for Value<N> {
    #[inline(always)]
    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
        &mut self.as_sequence_mut().unwrap()[i]
    }
}

impl<N: NestedValue> Index<&N> for Value<N> {
    type Output = N;

    #[inline(always)]
    fn index(&self, i: &N) -> &Self::Output {
        &(*self.as_dictionary().unwrap())[i]
    }
}

//---------------------------------------------------------------------------
// This part is a terrible hack

impl serde::Serialize for UnwrappedIOValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
        super::magic::output_value(serializer, self.clone().wrap())
    }
}

impl<'de> serde::Deserialize<'de> for UnwrappedIOValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
        Ok(super::magic::input_value::<'de, D>(deserializer)?.value_owned())
    }
}

//---------------------------------------------------------------------------

#[derive(Clone)]
pub struct Annotations<N: NestedValue>(Option<Box<Vec<N>>>);

impl<N: NestedValue> Annotations<N> {
    #[inline(always)]
    pub fn empty() -> Self {
        Annotations(None)
    }

    #[inline(always)]
    pub fn new(anns: Option<Vec<N>>) -> Self {
        Annotations(anns.map(Box::new))
    }

    #[inline(always)]
    pub fn maybe_slice(&self) -> Option<&[N]> {
        match &self.0 {
            None => None,
            Some(b) => Some(&b[..]),
        }
    }

    #[inline(always)]
    pub fn slice(&self) -> &[N] {
        self.maybe_slice().unwrap_or(&[])
    }

    #[inline(always)]
    pub fn to_vec(self) -> Vec<N> {
        use std::ops::DerefMut;
        self.0.map(|mut b| std::mem::take(b.deref_mut())).unwrap_or_default()
    }

    pub fn modify<F>(&mut self, f: F) -> &mut Self
    where
        F: FnOnce(&mut Vec<N>)
    {
        match &mut self.0 {
            None => {
                let mut v = Vec::new();
                f(&mut v);
                if !v.is_empty() {
                    self.0 = Some(Box::new(v));
                }
            }
            Some(b) => {
                use std::ops::DerefMut;
                f(b.deref_mut());
                if b.is_empty() {
                    self.0 = None;
                }
            }
        }
        self
    }

    pub fn copy_via<M: NestedValue, F, Err>(&self, f: &mut F) -> Result<Annotations<M>, Err>
    where
        F: FnMut(&N::Embedded) -> Result<Value<M>, Err>
    {
        Ok(match &self.0 {
            None =>
                Annotations(None),
            Some(b) =>
                Annotations(Some(Box::new(b.iter().map(|a| a.copy_via(f)).collect::<Result<Vec<_>, _>>()?))),
        })
    }
}

/// A possibly-annotated Value, with annotations (themselves
/// possibly-annotated) in order of appearance.
#[derive(Clone)]
pub struct AnnotatedValue<N: NestedValue>(pub Annotations<N>, pub Value<N>);

impl<N: NestedValue> AnnotatedValue<N> {
    #[inline(always)]
    fn new(anns: Annotations<N>, value: Value<N>) -> Self {
        AnnotatedValue(anns, value)
    }
}

impl<N: NestedValue> PartialEq for AnnotatedValue<N> {
    #[inline(always)]
    fn eq(&self, other: &Self) -> bool {
        self.1.eq(&other.1)
    }
}

impl<N: NestedValue> Eq for AnnotatedValue<N> {}

impl<N: NestedValue> Hash for AnnotatedValue<N> {
    #[inline(always)]
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.1.hash(state);
    }
}

impl<N: NestedValue> PartialOrd for AnnotatedValue<N> {
    #[inline(always)]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<N: NestedValue> Ord for AnnotatedValue<N> {
    #[inline(always)]
    fn cmp(&self, other: &Self) -> Ordering {
        self.1.cmp(&other.1)
    }
}

//---------------------------------------------------------------------------

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct PlainValue<D: Embeddable>(AnnotatedValue<PlainValue<D>>);

impl<D: Embeddable> PlainValue<D> {
    #[inline(always)]
    pub fn annotations_mut(&mut self) -> &mut Annotations<Self> {
        &mut (self.0).0
    }

    #[inline(always)]
    pub fn value_mut(&mut self) -> &mut Value<Self> {
        &mut (self.0).1
    }
}

impl<D: Embeddable> NestedValue for PlainValue<D> {
    type Embedded = D;

    #[inline(always)]
    fn wrap(anns: Annotations<Self>, v: Value<Self>) -> Self {
        PlainValue(AnnotatedValue::new(anns, v))
    }

    #[inline(always)]
    fn annotations(&self) -> &Annotations<Self> {
        &(self.0).0
    }

    #[inline(always)]
    fn value(&self) -> &Value<Self> {
        &(self.0).1
    }

    #[inline(always)]
    fn pieces(self) -> (Annotations<Self>, Value<Self>) {
        let AnnotatedValue(anns, v) = self.0;
        (anns, v)
    }

    #[inline(always)]
    fn value_owned(self) -> Value<Self> {
        (self.0).1
    }
}

impl<D: Embeddable> Debug for PlainValue<D> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.debug_fmt(f)
    }
}

//---------------------------------------------------------------------------

use std::rc::Rc;

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RcValue<D: Embeddable>(Rc<AnnotatedValue<RcValue<D>>>);

impl<D: Embeddable> NestedValue for RcValue<D> {
    type Embedded = D;

    #[inline(always)]
    fn wrap(anns: Annotations<Self>, v: Value<Self>) -> Self {
        RcValue(Rc::new(AnnotatedValue::new(anns, v)))
    }

    #[inline(always)]
    fn annotations(&self) -> &Annotations<Self> {
        &(self.0).0
    }

    #[inline(always)]
    fn value(&self) -> &Value<Self> {
        &(self.0).1
    }

    #[inline(always)]
    fn pieces(self) -> (Annotations<Self>, Value<Self>) {
        match Rc::try_unwrap(self.0) {
            Ok(AnnotatedValue(anns, v)) => (anns, v),
            Err(r) => (r.0.clone(), r.1.clone()),
        }
    }

    #[inline(always)]
    fn value_owned(self) -> Value<Self> {
        Rc::try_unwrap(self.0).unwrap_or_else(|_| panic!("value_owned on RcValue with refcount greater than one")).1
    }
}

impl<D: Embeddable> Debug for RcValue<D> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.debug_fmt(f)
    }
}

//---------------------------------------------------------------------------

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ArcValue<D: Embeddable>(Arc<AnnotatedValue<ArcValue<D>>>);

impl<D: Embeddable> NestedValue for ArcValue<D> {
    type Embedded = D;

    #[inline(always)]
    fn wrap(anns: Annotations<Self>, v: Value<Self>) -> Self {
        ArcValue(Arc::new(AnnotatedValue::new(anns, v)))
    }

    #[inline(always)]
    fn annotations(&self) -> &Annotations<Self> {
        &(self.0).0
    }

    #[inline(always)]
    fn value(&self) -> &Value<Self> {
        &(self.0).1
    }

    #[inline(always)]
    fn pieces(self) -> (Annotations<Self>, Value<Self>) {
        match Arc::try_unwrap(self.0) {
            Ok(AnnotatedValue(anns, v)) => (anns, v),
            Err(r) => (r.0.clone(), r.1.clone()),
        }
    }

    #[inline(always)]
    fn value_owned(self) -> Value<Self> {
        match Arc::try_unwrap(self.0) {
            Ok(AnnotatedValue(_anns, v)) => v,
            Err(r) => r.1.clone(),
        }
    }
}

impl<D: Embeddable> Debug for ArcValue<D> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.debug_fmt(f)
    }
}

//---------------------------------------------------------------------------

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct IOValue(Arc<AnnotatedValue<IOValue>>);
pub type UnwrappedIOValue = Value<IOValue>;

impl Domain for IOValue {
    fn debug_encode<W: Writer>(&self, w: &mut W) -> io::Result<()> {
        w.write(&mut IOValueDomainCodec, self)
    }
}

impl NestedValue for IOValue {
    type Embedded = Self;

    #[inline(always)]
    fn wrap(anns: Annotations<Self>, v: Value<Self>) -> Self {
        IOValue(Arc::new(AnnotatedValue::new(anns, v)))
    }

    #[inline(always)]
    fn annotations(&self) -> &Annotations<Self> {
        &(self.0).0
    }

    #[inline(always)]
    fn value(&self) -> &Value<Self> {
        &(self.0).1
    }

    #[inline(always)]
    fn pieces(self) -> (Annotations<Self>, Value<Self>) {
        match Arc::try_unwrap(self.0) {
            Ok(AnnotatedValue(anns, v)) => (anns, v),
            Err(r) => (r.0.clone(), r.1.clone()),
        }
    }

    #[inline(always)]
    fn value_owned(self) -> Value<Self> {
        match Arc::try_unwrap(self.0) {
            Ok(AnnotatedValue(_anns, v)) => v,
            Err(r) => r.1.clone(),
        }
    }
}

impl Debug for IOValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.debug_fmt(f)
    }
}

impl std::str::FromStr for IOValue {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        text::annotated_iovalue_from_str(s)
    }
}

impl serde::Serialize for IOValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
        super::magic::output_value(serializer, self.clone())
    }
}

impl<'de> serde::Deserialize<'de> for IOValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
        super::magic::input_value(deserializer)
    }
}

//---------------------------------------------------------------------------

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct DummyValue<D: Embeddable>(AnnotatedValue<DummyValue<D>>);

impl<D: Embeddable> Debug for DummyValue<D> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("<>")
    }
}

impl<D: Embeddable> DummyValue<D> {
    #[inline(always)]
    pub fn new() -> Self {
        DummyValue(AnnotatedValue::new(Annotations::empty(), Value::Boolean(false)))
    }
}

impl<D: Embeddable> NestedValue for DummyValue<D> {
    type Embedded = D;

    #[inline(always)]
    fn wrap(_anns: Annotations<Self>, _v: Value<Self>) -> Self {
        DummyValue::new()
    }

    #[inline(always)]
    fn annotations(&self) -> &Annotations<Self> {
        &self.0.0
    }

    #[inline(always)]
    fn value(&self) -> &Value<Self> {
        &self.0.1
    }

    #[inline(always)]
    fn pieces(self) -> (Annotations<Self>, Value<Self>) {
        (self.0.0, self.0.1)
    }

    #[inline(always)]
    fn value_owned(self) -> Value<Self> {
        self.0.1
    }
}

//---------------------------------------------------------------------------

// https://stackoverflow.com/questions/34304593/counting-length-of-repetition-in-macro/34324856
#[macro_export]
//#[allow(unused_macros)]
macro_rules! count__ {
    () => (0usize);
    ( $x:tt $($xs:tt)* ) => (1usize + $crate::count__!($($xs)*));
}

#[macro_export]
macro_rules! rec {
    ( $label:expr $(, $item:expr)* ) => {
        {
            let mut r__ = $crate::value::Value::record($label, $crate::count__!($($item)*));
            $(r__.fields_vec_mut().push($item);)*
            r__.finish().wrap()
        }
    }
}
