<commit_before>use std::result::Result as RResult;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use serde::de::MapVisitor as DeserializeMapVisitor;

use date::Date;

#[derive(Clone, Debug)]
pub struct Annotation {
    entry: Date,
    description: String
}

impl Annotation {

    pub fn new(entry: Date, description: String) -> Annotation {
        Annotation {
            entry: entry,
            description: description,
        }
    }

    pub fn entry(&self) -> &Date {
        &self.entry
    }

    pub fn description(&self) -> &String {
        &self.description
    }

}

impl Serialize for Annotation {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_struct("Annotation", AnnotationVisitor {
            value: self,
            state: 0,
        })
    }

}

struct AnnotationVisitor<'a> {
    value: &'a Annotation,
    state: u8,
}

impl<'a> MapVisitor for AnnotationVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, S::Error>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}

impl Deserialize for Annotation {

    fn deserialize<D>(deserializer: &mut D) -> RResult<Annotation, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &[
            "entry",
            "description"
        ];

        deserializer.deserialize_struct("Annotation", FIELDS, AnnotationDeserializeVisitor)
    }

}

struct AnnotationDeserializeVisitor;

impl Visitor for AnnotationDeserializeVisitor {
    type Value = Annotation;

    fn visit_map<V>(&mut self, mut visitor: V) -> RResult<Annotation, V::Error>
        where V: DeserializeMapVisitor
    {
        let mut entry       = None;
        let mut description = None;

        loop {
            let key : Option<String> = try!(visitor.visit_key());
            if key.is_none() {
                break;
            }
            let key = key.unwrap();

            match &key[..] {
                "entry" => {
                    entry = Some(try!(visitor.visit_value()));
                },
                "description" => {
                    description = Some(try!(visitor.visit_value()));<commit_msg>Add documentation for Annotation type<commit_after>use std::result::Result as RResult;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use serde::de::MapVisitor as DeserializeMapVisitor;

use date::Date;

/// Annotation type for task annotations.
/// Each annotation in taskwarrior consists of a date and a description,
/// the date is named "entry", the description "description" in the JSON export.
#[derive(Clone, Debug)]
pub struct Annotation {
    entry: Date,
    description: String
}

impl Annotation {

    /// Create a new Annotation object
    pub fn new(entry: Date, description: String) -> Annotation {
        Annotation {
            entry: entry,
            description: description,
        }
    }

    /// Get the entry date
    pub fn entry(&self) -> &Date {
        &self.entry
    }

    /// Get the description text
    pub fn description(&self) -> &String {
        &self.description
    }

}

impl Serialize for Annotation {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_struct("Annotation", AnnotationVisitor {
            value: self,
            state: 0,
        })
    }

}

/// Helper type for the `Serialize` implementation
struct AnnotationVisitor<'a> {
    value: &'a Annotation,
    state: u8,
}

impl<'a> MapVisitor for AnnotationVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, S::Error>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}

impl Deserialize for Annotation {

    fn deserialize<D>(deserializer: &mut D) -> RResult<Annotation, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &[
            "entry",
            "description"
        ];

        deserializer.deserialize_struct("Annotation", FIELDS, AnnotationDeserializeVisitor)
    }

}

/// Helper type for the `Deserialize` implementation
struct AnnotationDeserializeVisitor;

impl Visitor for AnnotationDeserializeVisitor {
    type Value = Annotation;

    fn visit_map<V>(&mut self, mut visitor: V) -> RResult<Annotation, V::Error>
        where V: DeserializeMapVisitor
    {
        let mut entry       = None;
        let mut description = None;

        loop {
            let key : Option<String> = try!(visitor.visit_key());
            if key.is_none() {
                break;
            }
            let key = key.unwrap();

            match &key[..] {
                "entry" => {
                    entry = Some(try!(visitor.visit_value()));
                },
                "description" => {
                    description = Some(try!(visitor.visit_value()));
{'fraction_non_alphanumeric': 0.12327169748459103, 'fraction_numerical': 0.001999000499750125, 'mean_word_length': 2.053916581892167, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 53, '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': '2594518', 'n_tokens_mistral': 1750, 'n_tokens_neox': 1716, 'n_words': 424}