Skip to content

Commit 6cae5b7

Browse files
committed
mocking up type mapping
1 parent a672e2a commit 6cae5b7

13 files changed

+199
-97
lines changed

types/src/date/date.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::{ Serialize, Deserialize, Serializer, Deserializer };
66
use super::{ DT, DefaultFormat };
77
use super::format::{ Format, ParseError };
88
use super::mapping::{ ElasticDateMapping, DefaultDateMapping };
9-
use ::mapping::{ ElasticMapping, ElasticType };
9+
use ::mapping::{ ElasticMapping, ElasticDataType };
1010

1111
pub use chrono::{ Datelike, Timelike };
1212

@@ -172,7 +172,7 @@ impl <F: Format, T: ElasticMapping<F> + ElasticDateMapping<F>> DateTime<F, T> {
172172
}
173173
}
174174

175-
impl <F: Format, T: ElasticMapping<F> + ElasticDateMapping<F>> ElasticType<T, F> for DateTime<F, T> {
175+
impl <F: Format, T: ElasticMapping<F> + ElasticDateMapping<F>> ElasticDataType<T, F> for DateTime<F, T> {
176176

177177
}
178178

types/src/date/format.rs

+55-54
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,12 @@ use chrono::format::{ Parsed, Item };
44
use std::error::Error;
55
use std::fmt;
66

7-
/// Represents an error encountered during parsing.
8-
#[derive(Debug)]
9-
pub struct ParseError {
10-
kind: ParseErrorKind
11-
}
12-
13-
#[derive_Debug]
14-
enum ParseErrorKind {
15-
Chrono(chrono::ParseError),
16-
Other(String)
17-
}
18-
19-
impl fmt::Display for ParseError {
20-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21-
match self.kind {
22-
ParseErrorKind::Chrono(ref err) => write!(f, "Chrono error: {}", err),
23-
ParseErrorKind::Other(ref err) => write!(f, "Error: {}", err)
24-
}
25-
}
26-
}
27-
28-
impl Error for ParseError {
29-
fn description(&self) -> &str {
30-
match self.kind {
31-
ParseErrorKind::Chrono(ref err) => err.description(),
32-
ParseErrorKind::Other(ref err) => &err[..]
33-
}
34-
}
35-
36-
fn cause(&self) -> Option<&Error> {
37-
match self.kind {
38-
ParseErrorKind::Chrono(ref err) => Some(err),
39-
ParseErrorKind::Other(_) => None
40-
}
41-
}
42-
}
43-
44-
impl From<chrono::ParseError> for ParseError {
45-
fn from(err: chrono::ParseError) -> ParseError {
46-
ParseError {
47-
kind: ParseErrorKind::Chrono(err)
48-
}
49-
}
50-
}
51-
52-
impl From<String> for ParseError {
53-
fn from(err: String) -> ParseError {
54-
ParseError {
55-
kind: ParseErrorKind::Other(err)
56-
}
57-
}
58-
}
59-
607
/// A format used for parsing and formatting dates.
618
///
629
/// The format is specified as two functions; `parse` and `format`, which are backed by `chrono::format::Item`s.
6310
/// Not all formats use the `Item`s though, for example `EpochMillis`, which is more efficient than other formats.
64-
pub trait Format {
11+
pub trait Format
12+
where Self : Default {
6513
/// Parses a date string to a `chrono::DateTime<UTC>` result.
6614
///
6715
/// The date string must match the format specified by `fmt()`.
@@ -121,3 +69,56 @@ pub trait Format {
12169
/// This is the string used when defining the format in the field mapping.
12270
fn name() -> &'static str;
12371
}
72+
73+
/// Represents an error encountered during parsing.
74+
#[derive(Debug)]
75+
pub struct ParseError {
76+
kind: ParseErrorKind
77+
}
78+
79+
#[derive_Debug]
80+
enum ParseErrorKind {
81+
Chrono(chrono::ParseError),
82+
Other(String)
83+
}
84+
85+
impl fmt::Display for ParseError {
86+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87+
match self.kind {
88+
ParseErrorKind::Chrono(ref err) => write!(f, "Chrono error: {}", err),
89+
ParseErrorKind::Other(ref err) => write!(f, "Error: {}", err)
90+
}
91+
}
92+
}
93+
94+
impl Error for ParseError {
95+
fn description(&self) -> &str {
96+
match self.kind {
97+
ParseErrorKind::Chrono(ref err) => err.description(),
98+
ParseErrorKind::Other(ref err) => &err[..]
99+
}
100+
}
101+
102+
fn cause(&self) -> Option<&Error> {
103+
match self.kind {
104+
ParseErrorKind::Chrono(ref err) => Some(err),
105+
ParseErrorKind::Other(_) => None
106+
}
107+
}
108+
}
109+
110+
impl From<chrono::ParseError> for ParseError {
111+
fn from(err: chrono::ParseError) -> ParseError {
112+
ParseError {
113+
kind: ParseErrorKind::Chrono(err)
114+
}
115+
}
116+
}
117+
118+
impl From<String> for ParseError {
119+
fn from(err: String) -> ParseError {
120+
ParseError {
121+
kind: ParseErrorKind::Other(err)
122+
}
123+
}
124+
}

types/src/date/formats.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{ Format, ParseError };
88
///
99
/// # Links
1010
/// - [Elasticsearch Doc](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
11-
#[derive(Debug, Clone)]
11+
#[derive(Debug, Clone, Default)]
1212
pub struct BasicDateTimeNoMillis;
1313
impl Format for BasicDateTimeNoMillis {
1414
fn fmt<'a>() -> Vec<Item<'a>> {
@@ -26,7 +26,7 @@ impl Format for BasicDateTimeNoMillis {
2626
///
2727
/// # Links
2828
/// - [Elasticsearch Doc](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
29-
#[derive(Debug, Clone)]
29+
#[derive(Debug, Clone, Default)]
3030
pub struct BasicDateTime;
3131
impl Format for BasicDateTime {
3232
fn fmt<'a>() -> Vec<Item<'a>>{
@@ -47,7 +47,7 @@ impl Format for BasicDateTime {
4747
///
4848
/// # Links
4949
/// - [Elasticsearch Doc](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
50-
#[derive(Debug, Clone)]
50+
#[derive(Debug, Clone, Default)]
5151
pub struct EpochMillis;
5252
impl Format for EpochMillis {
5353
fn fmt<'a>() -> Vec<Item<'a>>{

types/src/date/mapping.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use ::mapping::{ ElasticMapping, IndexAnalysis };
2020
/// use elastic_types::date::mapping::ElasticDateMapping;
2121
/// use elastic_types::date::{ BasicDateTime, Format };
2222
///
23+
/// #[derive(Default)]
2324
/// struct MyDateMapping;
2425
/// impl serde::Serialize for MyDateMapping {
2526
/// fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -41,7 +42,7 @@ use ::mapping::{ ElasticMapping, IndexAnalysis };
4142
///
4243
/// The above example binds the mapping to the `BasicDateTime` format, so `get_null_value` returns a properly formated value.
4344
pub trait ElasticDateMapping<T: Format>
44-
where Self : Sized + Serialize {
45+
where Self : Sized + Serialize + Default {
4546
/// Field-level index time boosting. Accepts a floating point number, defaults to `1.0`.
4647
fn boost() -> Option<f32> {
4748
None
@@ -99,14 +100,13 @@ where Self : Sized + Serialize {
99100
impl <T: Format, M: ElasticDateMapping<T>> ElasticMapping<T> for M {
100101
type Visitor = ElasticDateMappingVisitor<T, M>;
101102

102-
fn field_type() -> &'static str {
103+
fn data_type() -> &'static str {
103104
"date"
104105
}
105106
}
106107

107-
//TODO: Make this take in str for field name
108108
/// Default mapping for `DateTime`.
109-
#[derive(Debug, Clone)]
109+
#[derive(Debug, Clone, Default)]
110110
pub struct DefaultDateMapping<T: Format = DefaultFormat> {
111111
phantom: PhantomData<T>
112112
}
@@ -148,7 +148,7 @@ impl <F: Format, T: ElasticDateMapping<F>> Default for ElasticDateMappingVisitor
148148
impl <F: Format, T: ElasticDateMapping<F>> serde::ser::MapVisitor for ElasticDateMappingVisitor<F, T> {
149149
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
150150
where S: Serializer {
151-
try!(serializer.serialize_struct_elt("type", T::field_type()));
151+
try!(serializer.serialize_struct_elt("type", T::data_type()));
152152

153153
if let Some(boost) = T::boost() {
154154
try!(serializer.serialize_struct_elt("boost", boost));

types/src/mapping.rs

+24-17
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,26 @@ pub mod prelude {
55
//!
66
//! This is a convenience module to make it easy to build mappings for multiple types without too many `use` statements.
77
8-
pub use super::{ ElasticType, ElasticMapping, NullMapping, IndexAnalysis, ElasticMappingVisitor };
8+
pub use super::{ ElasticDataType, ElasticMapping, NullMapping, IndexAnalysis, ElasticMappingVisitor };
99
pub use ::date::mapping::*;
1010
pub use ::string::mapping::*;
1111
}
1212

1313
use std::marker::PhantomData;
1414
use serde;
1515

16-
/// The base requirements for mapping an Elasticsearch type.
16+
/// The base representation of an Elasticsearch data type.
1717
///
18-
/// Each type will have its own implementing structures with extra type-specific mapping parameters.
19-
pub trait ElasticMapping<F = ()> {
18+
/// # Links
19+
///
20+
/// - [Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html)
21+
pub trait ElasticDataType<T: ElasticMapping<F>, F> { }
22+
23+
/// The base requirements for mapping an Elasticsearch data type.
24+
///
25+
/// Each type has its own implementing structures with extra type-specific mapping parameters.
26+
pub trait ElasticMapping<F = ()>
27+
where Self: Default + serde::Serialize {
2028
/// The serialisation visitor used to inspect this mapping.
2129
type Visitor : serde::ser::MapVisitor + Default;
2230

@@ -31,43 +39,42 @@ pub trait ElasticMapping<F = ()> {
3139
}
3240

3341
/// Get the type name for this mapping, like `date` or `string`.
34-
fn field_type() -> &'static str {
42+
fn data_type() -> &'static str {
3543
""
3644
}
3745
}
3846

3947
/// A mapping implementation for a non-core type, or any where nobody cares about how it's mapped.
40-
#[derive(Debug, PartialEq)]
48+
#[derive(Debug, PartialEq, Default)]
4149
pub struct NullMapping;
4250
impl ElasticMapping for NullMapping {
4351
type Visitor = NullMappingVisitor;
52+
53+
fn data_type() -> &'static str {
54+
"object"
55+
}
4456
}
4557

4658
impl serde::Serialize for NullMapping {
47-
fn serialize<S>(&self, _: &mut S) -> Result<(), S::Error>
59+
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
4860
where S: serde::Serializer {
49-
Ok(())
61+
serializer.serialize_struct("mapping", NullMappingVisitor::default())
5062
}
5163
}
5264

5365
/// A default empty visitor.
5466
#[derive(Default, Debug, PartialEq)]
5567
pub struct NullMappingVisitor;
5668
impl serde::ser::MapVisitor for NullMappingVisitor {
57-
fn visit<S>(&mut self, _: &mut S) -> Result<Option<()>, S::Error>
69+
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
5870
where S: serde::Serializer {
71+
try!(serializer.serialize_struct_elt("type", NullMapping::data_type()));
72+
5973
Ok(None)
6074
}
6175
}
6276

63-
impl ElasticType<(), NullMapping> for .. { }
64-
65-
/// A type that can be indexed in Elasticsearch.
66-
//TODO: Rename to ElasticDataType
67-
pub trait ElasticType<T: ElasticMapping<F>, F> { }
68-
69-
//TODO: Need ElasticType, which is a main type that can be derived
70-
//This needs to map each property. Probably through a custom derive
77+
impl ElasticDataType<(), NullMapping> for .. { }
7178

7279
/// Should the field be searchable? Accepts `not_analyzed` (default) and `no`.
7380
#[derive(Debug, Clone, Copy)]

types/src/string/mapping.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
44
use std::marker::PhantomData;
55
use serde;
66
use serde::{ Serializer, Serialize };
7-
use ::mapping::{ ElasticMapping, ElasticType, IndexAnalysis };
7+
use ::mapping::{ ElasticMapping, ElasticDataType, IndexAnalysis };
88

99
/// The base requirements for mapping a `string` type.
1010
///
@@ -20,6 +20,7 @@ use ::mapping::{ ElasticMapping, ElasticType, IndexAnalysis };
2020
/// use elastic_types::mapping::ElasticMapping;
2121
/// use elastic_types::string::mapping::{ ElasticStringMapping, ElasticStringFieldMapping };
2222
///
23+
/// #[derive(Default)]
2324
/// struct MyStringMapping;
2425
/// impl serde::Serialize for MyStringMapping {
2526
/// fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -50,7 +51,7 @@ use ::mapping::{ ElasticMapping, ElasticType, IndexAnalysis };
5051
/// # }
5152
/// ```
5253
pub trait ElasticStringMapping
53-
where Self : Sized + Serialize {
54+
where Self : Sized + Serialize + Default {
5455
/// Field-level index time boosting. Accepts a floating point number, defaults to `1.0`.
5556
fn boost() -> Option<f32> {
5657
None
@@ -156,7 +157,7 @@ where Self : Sized + Serialize {
156157
impl <M: ElasticStringMapping> ElasticMapping for M {
157158
type Visitor = ElasticStringMappingVisitor<M>;
158159

159-
fn field_type() -> &'static str {
160+
fn data_type() -> &'static str {
160161
"string"
161162
}
162163
}
@@ -466,7 +467,7 @@ impl serde::Serialize for TermVector {
466467
}
467468

468469
/// Default mapping for `String`.
469-
#[derive(Debug, Clone)]
470+
#[derive(Debug, Clone, Default)]
470471
pub struct DefaultStringMapping;
471472
impl ElasticStringMapping for DefaultStringMapping { }
472473

@@ -479,9 +480,8 @@ impl Serialize for DefaultStringMapping {
479480
}
480481

481482
/// A Rust representation of an Elasticsearch `string`.
482-
pub trait ElasticStringType<T: ElasticMapping + ElasticStringMapping> where Self: Sized + ElasticType<T, ()> { }
483+
pub trait ElasticStringType<T: ElasticMapping + ElasticStringMapping> where Self: Sized + ElasticDataType<T, ()> { }
483484

484-
//TODO: Make this take in str for field name
485485
/// Base visitor for serialising string mappings.
486486
#[derive(Debug, PartialEq)]
487487
pub struct ElasticStringMappingVisitor<T: ElasticMapping> {
@@ -500,7 +500,7 @@ impl <T: ElasticMapping + ElasticStringMapping> serde::ser::MapVisitor for Elast
500500
#[allow(cyclomatic_complexity)]
501501
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
502502
where S: serde::Serializer {
503-
try!(serializer.serialize_struct_elt("type", T::field_type()));
503+
try!(serializer.serialize_struct_elt("type", T::data_type()));
504504

505505
if let Some(boost) = T::boost() {
506506
try!(serializer.serialize_struct_elt("boost", boost));

types/src/string/string.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::marker::PhantomData;
22
use serde;
33
use serde::{ Serialize, Deserialize, Serializer, Deserializer };
44
use super::mapping::{ ElasticStringType, ElasticStringMapping, DefaultStringMapping };
5-
use ::mapping::{ ElasticMapping, ElasticType };
5+
use ::mapping::{ ElasticMapping, ElasticDataType };
66

77
/// An Elasticsearch `string` with a mapping.
88
///
@@ -58,7 +58,7 @@ impl <T: ElasticMapping + ElasticStringMapping> ElasticString<T> {
5858
}
5959
}
6060

61-
impl <T: ElasticMapping + ElasticStringMapping> ElasticType<T, ()> for ElasticString<T> { }
61+
impl <T: ElasticMapping + ElasticStringMapping> ElasticDataType<T, ()> for ElasticString<T> { }
6262
impl <T: ElasticMapping + ElasticStringMapping> ElasticStringType<T> for ElasticString<T> { }
6363

6464
impl From<String> for ElasticString<DefaultStringMapping> {
@@ -119,7 +119,7 @@ impl<'a, T: ElasticMapping + ElasticStringMapping> PartialEq<ElasticString<T>> f
119119
}
120120
}
121121

122-
impl ElasticType<DefaultStringMapping, ()> for String { }
122+
impl ElasticDataType<DefaultStringMapping, ()> for String { }
123123
impl ElasticStringType<DefaultStringMapping> for String { }
124124

125125
//Serialize elastic string

0 commit comments

Comments
 (0)