uninode 0.4.2

Universal object type
Documentation
//
// Copyright (c) 2022 Oleg Lelenkov <o.lelenkov@gmail.com>
// Distributed under terms of the BSD 3-Clause license.
//

use std::{fmt, result, error::Error};
use crate::value::UniNode;
use serde::{ser, de};
use serde::de::Unexpected;

#[derive(Debug)]
pub enum UniNodeSerError {
    KeyMustBeAString,
    Custom(String),
    MissingField(String),
    UnknownVariant(String, Vec<String>),
}

pub type Result<T> = result::Result<T, UniNodeSerError>;

struct OneOf<'a>(&'a [String]);

impl<'a> fmt::Display for OneOf<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.0.len() {
            0 => panic!(),
            1 => write!(f, "'{}'", self.0[0]),
            2 => write!(f, "'{}' or '{}'", self.0[0], self.0[1]),
            _ => {
                write!(f, "one of ")?;
                for (i, v) in self.0.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "'{}'", v)?;
                }
                Ok(())
            },
        }
    }
}

impl fmt::Display for UniNodeSerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            UniNodeSerError::KeyMustBeAString => {
                f.write_str("key must be a string")
            },
            UniNodeSerError::Custom(msg) => f.write_str(msg),
            UniNodeSerError::MissingField(fld) => {
                write!(f, "Missing field '{}'", fld)
            },
            UniNodeSerError::UnknownVariant(v, exp) => {
                if exp.is_empty() {
                    write!(f, "Unknown variant '{}'", v)
                } else {
                    let one = OneOf(exp.as_slice());
                    write!(f, "Unknown variant '{}', expected {}", v, one)
                }
            },
        }
    }
}

impl Error for UniNodeSerError {}

impl ser::Error for UniNodeSerError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        UniNodeSerError::Custom(msg.to_string())
    }
}

impl de::Error for UniNodeSerError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        UniNodeSerError::Custom(msg.to_string())
    }

    fn missing_field(field: &'static str) -> Self {
        UniNodeSerError::MissingField(String::from(field))
    }

    fn unknown_variant(
        variant: &str, expected: &'static [&'static str],
    ) -> Self {
        let expected = expected.iter().map(|&v| String::from(v)).collect();
        UniNodeSerError::UnknownVariant(String::from(variant), expected)
    }
}

impl UniNode {
    pub fn invalid_type(&self, exp: &dyn de::Expected) -> UniNodeSerError {
        <UniNodeSerError as serde::de::Error>::invalid_type(self.into(), exp)
    }
}

impl<'a> From<&'a UniNode> for Unexpected<'a> {
    fn from(val: &'a UniNode) -> Unexpected<'a> {
        match val {
            UniNode::Null => Unexpected::Unit,
            UniNode::Boolean(val) => Unexpected::Bool(*val),
            UniNode::Integer(val) => Unexpected::Signed(*val),
            UniNode::UInteger(val) => Unexpected::Unsigned(*val),
            UniNode::Float(val) => Unexpected::Float(*val),
            UniNode::String(val) => Unexpected::Str(val),
            UniNode::Bytes(val) => {
                Unexpected::Bytes(&val[0..val.len().min(10)])
            },
            UniNode::Array(_) => Unexpected::Seq,
            UniNode::Object(_) => Unexpected::Map,
        }
    }
}