<commit_before>use std::convert::From;
use std::io;
use std::io::Write;
use std::result::Result;

use byteorder;
use byteorder::WriteBytesExt;

use super::{
    Marker,
};

/// Represents an error that can occur when attempting to write MessagePack'ed value into the write.
#[derive(Debug)]
pub struct WriteError(io::Error);

impl From<byteorder::Error> for WriteError {
    fn from(err: byteorder::Error) -> WriteError {
        match err {
            byteorder::Error::UnexpectedEOF => unimplemented!(),
            byteorder::Error::Io(err) => WriteError(err),
        }
    }
}

// TODO: Split Error for each function, permitting each function to return variant with impossible values.
#[derive(Debug)]
pub enum Error {
    /// Unable to write the value with the given type
    TypeMismatch,
    /// IO error while writing marker.
    InvalidMarkerWrite(WriteError),
    /// IO error while writing single-byte data.
    InvalidFixedValueWrite(WriteError),
    /// IO error while writing data.
    InvalidDataWrite(WriteError),
}

fn write_marker<W>(wr: &mut W, marker: Marker) -> Result<(), Error>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(Error::InvalidMarkerWrite(From::from(err)))
    }
}

fn write_fixval<W>(wr: &mut W, marker: Marker) -> Result<(), Error>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(Error::InvalidFixedValueWrite(From::from(err)))
    }
}

/// Represents an error that can happen while writing MessagePack single-byte value.
#[derive(Debug)]
pub struct FixedValueWriteError(WriteError);

fn write_fixval_<W>(wr: &mut W, marker: Marker) -> Result<(), FixedValueWriteError>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(FixedValueWriteError(From::from(err)))
    }
}

/// Encodes and attempts to write a nil value into the given write.
///
/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
///
/// # Errors
///
/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the nil
/// marker.
pub fn write_nil<W>(wr: &mut W) -> Result<(), FixedValueWriteError>
    where W: Write
{
    write_fixval_(wr, Marker::Null)
}

/// Encodes and attempts to write a bool value into the given write.
///
/// According to the MessagePack specification, an encoded boolean value is represented as a single
/// byte.
///
/// # Errors
///
/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the
/// boolean marker.
pub fn write_bool<W>(wr: &mut W, val: bool) -> Result<(), FixedValueWriteError>
    where W: Write
{
    match val {
        true  => write_fixval_(wr, Marker::True),
        false => write_fixval_(wr, Marker::False)
    }
}

// With strictly type checking.
// TODO: Docs.
pub fn write_pfix<W>(wr: &mut W, val: u8) -> Result<(), FixedValueWriteError>
    where W: Write
{
    assert!(val < 128);

    write_fixval_(wr, Marker::PositiveFixnum(val))
}

pub fn write_nfix<W>(wr: &mut W, val: i8) -> Result<(), Error>
    where W: Write
{
    if -32 <= val && val < 0 {
        write_fixval(wr, Marker::NegativeFixnum(val))
    } else {
        Err(Error::TypeMismatch)
    }
}

macro_rules! make_write_data_fn {
    (deduce, $writer:ident, $encoder:ident, 0, $val:ident)
        => ($writer.$encoder($val););
    (deduce, $writer:ident, $encoder:ident, 1, $val:ident)
        => ($writer.$encoder::<byteorder::BigEndian>($val););
    (gen, $t:ty, $d:tt, $name:ident, $encoder:ident) => {
        fn $name<W>(wr: &mut W, val: $t) -> Result<(), Error>
            where W: Write
        {
            match make_write_data_fn!(deduce, wr, $encoder, $d, val) {
                Ok(data) => Ok(data),
                Err(err) => Err(Error::InvalidDataWrite(From::from(err))),
            }<commit_msg>[Encode] Documentation pack.<commit_after>use std::convert::From;
use std::io;
use std::io::Write;
use std::result::Result;

use byteorder;
use byteorder::WriteBytesExt;

use super::{
    Marker,
};

/// Represents an error that can occur when attempting to write MessagePack'ed value into the write.
#[derive(Debug)]
pub struct WriteError(io::Error);

impl From<byteorder::Error> for WriteError {
    fn from(err: byteorder::Error) -> WriteError {
        match err {
            byteorder::Error::UnexpectedEOF => unimplemented!(),
            byteorder::Error::Io(err) => WriteError(err),
        }
    }
}

// TODO: Split Error for each function, permitting each function to return variant with impossible values.
#[derive(Debug)]
pub enum Error {
    /// Unable to write the value with the given type
    TypeMismatch,
    /// IO error while writing marker.
    InvalidMarkerWrite(WriteError),
    /// IO error while writing single-byte data.
    InvalidFixedValueWrite(WriteError),
    /// IO error while writing data.
    InvalidDataWrite(WriteError),
}

fn write_marker<W>(wr: &mut W, marker: Marker) -> Result<(), Error>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(Error::InvalidMarkerWrite(From::from(err)))
    }
}

fn write_fixval<W>(wr: &mut W, marker: Marker) -> Result<(), Error>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(Error::InvalidFixedValueWrite(From::from(err)))
    }
}

/// Represents an error that can happen while writing MessagePack single-byte value.
#[derive(Debug)]
pub struct FixedValueWriteError(WriteError);

fn write_fixval_<W>(wr: &mut W, marker: Marker) -> Result<(), FixedValueWriteError>
    where W: Write
{
    let byte = marker.to_u8();

    match wr.write_u8(byte) {
        Ok(())   => Ok(()),
        Err(err) => Err(FixedValueWriteError(From::from(err)))
    }
}

/// Encodes and attempts to write a nil value into the given write.
///
/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
///
/// # Errors
///
/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the nil
/// marker.
pub fn write_nil<W>(wr: &mut W) -> Result<(), FixedValueWriteError>
    where W: Write
{
    write_fixval_(wr, Marker::Null)
}

/// Encodes and attempts to write a bool value into the given write.
///
/// According to the MessagePack specification, an encoded boolean value is represented as a single
/// byte.
///
/// # Errors
///
/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the
/// boolean marker.
pub fn write_bool<W>(wr: &mut W, val: bool) -> Result<(), FixedValueWriteError>
    where W: Write
{
    match val {
        true  => write_fixval_(wr, Marker::True),
        false => write_fixval_(wr, Marker::False)
    }
}

/// Encodes and attempts to write an unsigned small integer value as a fixint into the given write.
///
/// According to the MessagePack specification, a positive fixed integer value is represented using
/// a single byte in `[0x00; 0x7f]` range inclusively, prepended with a special marker mask.
///
/// The function is **strict** with the input arguments - it is the user's responsibility to check
/// if the value fits in the described range, otherwise it will panic.
///
/// If you are not sure if the value fits in the given range use `write_uint` instead, which
/// automatically selects the appropriate integer representation.
///
/// # Errors
///
/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the
/// positive integer marker.
///
/// # Panics
///
/// Panics if `val` is greater than 127.
pub fn write_pfix<W>(wr: &mut W, val: u8) -> Result<(), FixedValueWriteError>
    where W: Write
{
    assert!(val < 128);

    write_fixval_(wr, Marker::PositiveFixnum(val))
}

pub fn write_nfix<W>(wr: &mut W, val: i8) -> Result<(), Error>
    where W: Write
{
    if -32 <= val && val < 0 {
        write_fixval(wr, Marker::NegativeFixnum(val))
    } else {
        Err(Error::TypeMismatch)
    }
}

macro_rules! make_write_data_fn {
    (deduce, $writer:ident, $encoder:ident, 0, $val:ident)
        => ($writer.$encoder($val););
    (deduce, $writer:ident, $encoder:ident, 1, $val:ident)
        => ($writer.$encoder::<byteorder::BigEndian>($val););
    (gen, $t:ty, $d:tt, $name:ident, $encoder:ident) => {
        fn $name<W>(wr: &mut W, val: $t) -> Result<(), Error>
            where W: Write
        {
            match make_write_data_fn!(deduce, wr, $encoder, $d, val) {
                Ok(data) => Ok(data),
                Err(err) => Err(Error::InvalidDataWrite(From::from(err))),
            }
{'fraction_non_alphanumeric': 0.14922502545536825, 'fraction_numerical': 0.0049779386808462495, 'mean_word_length': 3.107806691449814, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2440456', 'n_tokens_mistral': 2816, 'n_tokens_neox': 2763, 'n_words': 859}