use std::marker::PhantomData;
use super::{Date, DateFormat, DefaultDateFormat, FormattableDateValue};
pub trait DateFieldType<TMapping>
where
Self: Into<FormattableDateValue<TMapping::Format>>,
TMapping: DateMapping,
{
}
pub trait DateMapping
where
Self: Default,
{
type Format: DateFormat;
fn boost() -> Option<f32> {
None
}
fn doc_values() -> Option<bool> {
None
}
fn include_in_all() -> Option<bool> {
None
}
fn index() -> Option<bool> {
None
}
fn store() -> Option<bool> {
None
}
fn ignore_malformed() -> Option<bool> {
None
}
fn null_value() -> Option<Date<Self>> {
None
}
}
#[derive(PartialEq, Debug, Default, Clone, Copy)]
pub struct DefaultDateMapping<TFormat = DefaultDateFormat>
where
TFormat: DateFormat,
{
_f: PhantomData<TFormat>,
}
impl<TFormat> DateMapping for DefaultDateMapping<TFormat>
where
TFormat: DateFormat,
{
type Format = TFormat;
}
mod private {
use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
use date::{DateFormat, FormattableDateValue};
use private::field::{DocumentField, FieldMapping, FieldType};
use super::{DateFieldType, DateMapping};
impl<TField, TMapping> FieldType<TMapping, DatePivot> for TField
where
TField: DateFieldType<TMapping> + Serialize,
TField: Into<FormattableDateValue<TMapping::Format>>,
TMapping: DateMapping,
{
}
#[derive(Default)]
pub struct DatePivot;
impl<TMapping, TFormat> FieldMapping<DatePivot> for TMapping
where
TMapping: DateMapping<Format = TFormat>,
TFormat: DateFormat,
{
type DocumentField = DocumentField<TMapping, DatePivot>;
fn data_type() -> &'static str {
"date"
}
}
impl<TMapping, TFormat> Serialize for DocumentField<TMapping, DatePivot>
where
TMapping: FieldMapping<DatePivot> + DateMapping<Format = TFormat>,
TFormat: DateFormat,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = try!(serializer.serialize_struct("mapping", 9));
try!(state.serialize_field("type", TMapping::data_type()));
try!(state.serialize_field("format", TMapping::Format::name()));
ser_field!(state, "boost", TMapping::boost());
ser_field!(state, "doc_values", TMapping::doc_values());
ser_field!(state, "include_in_all", TMapping::include_in_all());
ser_field!(state, "index", TMapping::index());
ser_field!(state, "store", TMapping::store());
ser_field!(state, "ignore_malformed", TMapping::ignore_malformed());
ser_field!(state, "null_value", TMapping::null_value());
state.end()
}
}
}
#[cfg(test)]
mod tests {
use serde_json;
use chrono::{DateTime, Utc};
use prelude::*;
use private::field::{DocumentField, FieldType};
#[derive(Default, Clone)]
pub struct MyDateMapping;
impl DateMapping for MyDateMapping {
type Format = EpochMillis;
fn null_value() -> Option<Date<Self>> {
Some(Date::build(2015, 3, 14, 16, 45, 13, 778))
}
fn boost() -> Option<f32> {
Some(1.01)
}
fn index() -> Option<bool> {
Some(true)
}
fn doc_values() -> Option<bool> {
Some(true)
}
fn include_in_all() -> Option<bool> {
Some(false)
}
fn store() -> Option<bool> {
Some(true)
}
fn ignore_malformed() -> Option<bool> {
Some(true)
}
}
#[test]
fn datetime_has_default_mapping() {
assert_eq!(
DefaultDateMapping::<ChronoFormat>::default(),
DateTime::<Utc>::field_mapping()
);
}
#[test]
fn serialise_mapping_default() {
let ser = serde_json::to_string(&DocumentField::from(
DefaultDateMapping::<DefaultDateFormat>::default(),
)).unwrap();
let expected = json_str!({
"type": "date",
"format": "basic_date_time"
});
assert_eq!(expected, ser);
}
#[test]
fn serialise_mapping_custom() {
let ser = serde_json::to_string(&DocumentField::from(MyDateMapping)).unwrap();
let expected = json_str!({
"type": "date",
"format": "epoch_millis",
"boost": 1.01,
"doc_values": true,
"include_in_all": false,
"index": true,
"store": true,
"ignore_malformed": true,
"null_value": "1426351513778"
});
assert_eq!(expected, ser);
}
}