This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 43e3fee  IGNITE-1472: Enum support for C++
43e3fee is described below

commit 43e3fee444c55fe12da3b9d57606f0b6b8df1886
Author: Igor Sapego <isap...@apache.org>
AuthorDate: Fri Jul 12 19:23:32 2019 +0300

    IGNITE-1472: Enum support for C++
    
    This closes #6649
---
 .../cpp/binary/include/ignite/binary/binary_enum.h | 204 +++++++++++++++++++++
 .../include/ignite/binary/binary_enum_entry.h      | 107 +++++++++++
 .../include/ignite/binary/binary_raw_reader.h      |  23 +++
 .../include/ignite/binary/binary_raw_writer.h      |  21 +++
 .../binary/include/ignite/binary/binary_reader.h   |  23 +++
 .../cpp/binary/include/ignite/binary/binary_type.h |   8 +-
 .../binary/include/ignite/binary/binary_writer.h   |  22 +++
 .../include/ignite/impl/binary/binary_common.h     |   6 +
 .../ignite/impl/binary/binary_reader_impl.h        |  84 ++++++++-
 .../include/ignite/impl/binary/binary_utils.h      |  82 ++++++---
 .../ignite/impl/binary/binary_writer_impl.h        |  69 ++++++-
 .../ignite/impl/interop/interop_input_stream.h     |   4 +-
 .../platforms/cpp/binary/project/vs/binary.vcxproj |   2 +
 .../cpp/binary/project/vs/binary.vcxproj.filters   |   6 +
 .../cpp/binary/src/binary/binary_raw_reader.cpp    |   5 +
 .../cpp/binary/src/binary/binary_raw_writer.cpp    |   5 +
 .../cpp/binary/src/binary/binary_reader.cpp        |   5 +
 .../cpp/binary/src/binary/binary_writer.cpp        |   5 +
 .../binary/src/impl/binary/binary_reader_impl.cpp  |  85 ++++++---
 .../cpp/binary/src/impl/binary/binary_utils.cpp    |  43 +++--
 .../binary/src/impl/binary/binary_writer_impl.cpp  |  21 +++
 .../core-test/include/ignite/binary_test_defs.h    |  58 ++++++
 .../cpp/core-test/src/binary_object_test.cpp       | 117 ++++++++++++
 modules/platforms/cpp/core-test/src/cache_test.cpp |  50 ++++-
 24 files changed, 976 insertions(+), 79 deletions(-)

diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h
new file mode 100644
index 0000000..dd2f37c
--- /dev/null
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Declares ignite::binary::BinaryEnum class template and helping classes
+ * to declare enum type specialization for user types.
+ */
+
+#ifndef _IGNITE_BINARY_BINARY_ENUM
+#define _IGNITE_BINARY_BINARY_ENUM
+
+#include <stdint.h>
+
+#include <ignite/common/common.h>
+
+#include <ignite/binary/binary_type.h>
+
+namespace ignite
+{
+    namespace binary
+    {
+        /**
+         * Binary enum structure. Defines a set of functions required for enum 
type to be serialized and deserialized.
+         *
+         * Methods that should be defined:
+         *   static void GetTypeName(std::string& dst) - should place type 
name in @c dst parameter. This method should
+         *     always return the same value.
+         *   static int32_t GetTypeId() - should return Type ID.
+         *   static int32_t GetOrdinal(T) - should return ordinal value for 
enum value.
+         *   static T FromOrdinal(int32_t) - should return enum value for a 
given ordinal value.
+         *   static bool IsNull(const T&) - check whether passed enum object 
should be interpreted as NULL.
+         *   static void GetNull(T&) - get NULL value for the given enum type.
+         *
+         * It is recommended to use BinaryEnumDefault as a base class for 
default implementation of GetTypeId(),
+         * GetOrdinal() and FromOrdinal() methods for plain enum types. In 
this case, only GetTypeName() should be
+         * implemented by a user directly.
+         */
+        template<typename T>
+        struct BinaryEnum { };
+
+        /**
+         * Default implementations of BinaryEnum.
+         */
+        template<typename T>
+        struct BinaryEnumDefault
+        {
+            /**
+             * Get type ID for the enum type.
+             *
+             * @return Type ID.
+             */
+            static int32_t GetTypeId()
+            {
+                std::string typeName;
+                BinaryEnum<T>::GetTypeName(typeName);
+
+                return GetBinaryStringHashCode(typeName.c_str());
+            }
+
+            /**
+             * Get enum type ordinal.
+             *
+             * @return Ordinal of the enum type.
+             */
+            static int32_t GetOrdinal(T value)
+            {
+                return static_cast<int32_t>(value);
+            }
+
+            /**
+             * Get enum value for the given ordinal value.
+             *
+             * @param ordinal Ordinal value of the enum.
+             */
+            static T FromOrdinal(int32_t ordinal)
+            {
+                return static_cast<T>(ordinal);
+            }
+        };
+
+        /**
+         * Implementations of BinaryEnum nullability when INT32_MIN ordinal 
value used as a NULL indicator.
+         */
+        template<typename T>
+        struct BinaryEnumIntMinNull
+        {
+            /**
+             * Check whether passed binary object should be interpreted as 
NULL.
+             *
+             * @return True if binary object should be interpreted as NULL.
+             */
+            static bool IsNull(const T& val)
+            {
+                return val == BinaryEnum<T>::FromOrdinal(INT32_MIN);
+            }
+
+            /**
+             * Get NULL value for the given binary type.
+             *
+             * @param dst Null value for the type.
+             */
+            static void GetNull(T& dst)
+            {
+                dst = BinaryEnum<T>::FromOrdinal(INT32_MIN);
+            }
+        };
+
+        /**
+         * Default implementations of BinaryType hashing functions and 
non-null type behaviour.
+         */
+        template<typename T>
+        struct BinaryEnumDefaultAll :
+            BinaryEnumDefault<T>,
+            BinaryEnumIntMinNull<T> { };
+
+        /**
+         * BinaryEnum template specialization for pointers.
+         */
+        template <typename T>
+        struct BinaryEnum<T*>
+        {
+            /** Actual type. */
+            typedef BinaryEnum<T> BinaryEnumDereferenced;
+
+            /**
+             * Get binary object type ID.
+             *
+             * @return Type ID.
+             */
+            static int32_t GetTypeId()
+            {
+                return BinaryEnumDereferenced::GetTypeId();
+            }
+
+            /**
+             * Get binary object type name.
+             *
+             * @param dst Output type name.
+             */
+            static void GetTypeName(std::string& dst)
+            {
+                BinaryEnumDereferenced::GetTypeName(dst);
+            }
+
+            /**
+             * Get enum type ordinal.
+             *
+             * @return Ordinal of the enum type.
+             */
+            static int32_t GetOrdinal(T* value)
+            {
+                return BinaryEnumDereferenced::GetOrdinal(*value);
+            }
+
+            /**
+             * Get enum value for the given ordinal value.
+             *
+             * @param ordinal Ordinal value of the enum.
+             */
+            static T* FromOrdinal(int32_t ordinal)
+            {
+                return new T(BinaryEnumDereferenced::FromOrdinal(ordinal));
+            }
+
+            /**
+             * Check whether passed enum should be interpreted as NULL.
+             *
+             * @param obj Enum value to test.
+             * @return True if enum value should be interpreted as NULL.
+             */
+            static bool IsNull(T* const& obj)
+            {
+                return !obj || BinaryEnumDereferenced::IsNull(*obj);
+            }
+
+            /**
+             * Get NULL value for the enum type.
+             *
+             * @param dst NULL value for the enum.
+             */
+            static void GetNull(T*& dst)
+            {
+                dst = 0;
+            }
+        };
+    }
+}
+
+#endif //_IGNITE_BINARY_BINARY_ENUM
diff --git 
a/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h
new file mode 100644
index 0000000..8a27506
--- /dev/null
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Declares ignite::binary::BinaryEnumEntry class.
+ */
+
+#ifndef _IGNITE_BINARY_BINARY_ENUM_ENTRY
+#define _IGNITE_BINARY_BINARY_ENUM_ENTRY
+
+#include <stdint.h>
+
+#include <ignite/common/common.h>
+
+namespace ignite
+{
+    namespace binary
+    {
+        /**
+         * Binary enum entry.
+         *
+         * Represents a single entry of enum in a binary form.
+         */
+        class IGNITE_IMPORT_EXPORT BinaryEnumEntry
+        {
+        public:
+            /**
+             * Default constructor.
+             */
+            BinaryEnumEntry() :
+                typeId(0),
+                ordinal(0)
+            {
+                // No-op.
+            }
+
+            /**
+             * Constructor.
+             *
+             * @param typeId Type ID of the enum.
+             * @param ordinal Ordinal of the enum value.
+             */
+            BinaryEnumEntry(int32_t typeId, int32_t ordinal) :
+                typeId(typeId),
+                ordinal(ordinal)
+            {
+                // No-op.
+            }
+
+            /**
+             * Get type ID.
+             * Type ID can never equal zero. If the Type ID equals zero, the 
instance is not valid, and could only be
+             * acquired by manual construction or by reading NULL value.
+             *
+             * @return Type ID.
+             */
+            int32_t GetTypeId() const
+            {
+                return typeId;
+            }
+
+            /**
+             * Get ordinal of the enum value.
+             *
+             * @return Ordinal.
+             */
+            int32_t GetOrdinal() const
+            {
+                return ordinal;
+            }
+
+            /**
+             * Check whether value was acquired by reading a NULL value.
+             *
+             * @return @c true if acquired by reading a NULL value.
+             */
+            bool IsNull() const
+            {
+                return typeId == 0;
+            }
+
+        private:
+            /** Type ID. */
+            int32_t typeId;
+
+            /** Ordinal value. */
+            int32_t ordinal;
+        };
+    }
+}
+
+#endif //_IGNITE_BINARY_BINARY_ENUM_ENTRY
diff --git 
a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
index dd7a696..a8efad9 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h
@@ -31,6 +31,7 @@
 #include "ignite/impl/binary/binary_reader_impl.h"
 #include "ignite/binary/binary_consts.h"
 #include "ignite/binary/binary_containers.h"
+#include "ignite/binary/binary_enum_entry.h"
 #include "ignite/guid.h"
 #include "ignite/date.h"
 #include "ignite/timestamp.h"
@@ -352,6 +353,13 @@ namespace ignite
             BinaryStringArrayReader ReadStringArray();
 
             /**
+             * Read enum entry.
+             *
+             * @return Enum entry.
+             */
+            BinaryEnumEntry ReadBinaryEnum();
+
+            /**
              * Start array read.
              *
              * Every time you get a BinaryArrayReader from BinaryRawReader you
@@ -443,6 +451,8 @@ namespace ignite
              * Read object.
              *
              * @return Object.
+             *
+             * @trapam T Object type. BinaryType class template should be 
specialized for the type.
              */
             template<typename T>
             T ReadObject()
@@ -451,6 +461,19 @@ namespace ignite
             }
 
             /**
+             * Read enum value.
+             *
+             * @return Enum value.
+             *
+             * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+             */
+            template<typename T>
+            T ReadEnum()
+            {
+                return impl->ReadEnum<T>();
+            }
+
+            /**
              * Try read object.
              * Reads value, stores it to res and returns true if the value is
              * not null. Otherwise just returns false.
diff --git 
a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h
index 857d7f2..8150db0 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h
@@ -283,6 +283,13 @@ namespace ignite
             BinaryStringArrayWriter WriteStringArray();
 
             /**
+             * Write enum entry.
+             *
+             * @param entry Binary enum entry.
+             */
+            void WriteBinaryEnum(BinaryEnumEntry entry);
+
+            /**
              * Write NULL value.
              */
             void WriteNull();
@@ -415,6 +422,20 @@ namespace ignite
             {
                 impl->WriteObject<T>(val);
             }
+
+            /**
+             * Write binary enum entry.
+             *
+             * @param val Binary enum entry.
+             *
+             * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+             */
+            template<typename T>
+            void WriteEnum(T val)
+            {
+                impl->WriteEnum(val);
+            }
+
         private:
             /** Implementation delegate. */
             ignite::impl::binary::BinaryWriterImpl* impl; 
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h
index acd9d61..be4badc 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h
@@ -366,6 +366,14 @@ namespace ignite
             BinaryStringArrayReader ReadStringArray(const char* fieldName);
 
             /**
+             * Read enum entry.
+             *
+             * @param fieldName Field name.
+             * @return Enum entry.
+             */
+            BinaryEnumEntry ReadBinaryEnum(const char* fieldName);
+
+            /**
              * Start array read.
              *
              * Every time you get a BinaryArrayReader from BinaryReader you
@@ -464,6 +472,8 @@ namespace ignite
              *
              * @param fieldName Field name.
              * @return Object.
+             *
+             * @trapam T Object type. BinaryType class template should be 
specialized for the type.
              */
             template<typename T>
             T ReadObject(const char* fieldName)
@@ -472,6 +482,19 @@ namespace ignite
             }
 
             /**
+             * Read enum value.
+             *
+             * @return Enum value.
+             *
+             * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+             */
+            template<typename T>
+            T ReadEnum(const char* fieldName)
+            {
+                return impl->ReadEnum<T>(fieldName);
+            }
+
+            /**
              * Get raw reader for this reader.
              *
              * @return Raw reader.
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h
index 84de648..492de03 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h
@@ -18,7 +18,7 @@
 /**
  * @file
  * Declares ignite::binary::BinaryType class template and helping macros
- * to declare binary type specialisation for user types.
+ * to declare binary type specialization for user types.
  */
 
 #ifndef _IGNITE_BINARY_BINARY_TYPE
@@ -108,7 +108,7 @@ static bool IsNull(const T& obj) \
 
 /**
  * @def IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(T)
- * Implementation of GetNull() function which returns an instance created with 
defult constructor.
+ * Implementation of GetNull() function which returns an instance created with 
default constructor.
  */
 #define IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(T) \
 static void GetNull(T& dst) \
@@ -215,7 +215,7 @@ namespace ignite
             BinaryTypeNonNullableType<T> { };
 
         /**
-         * Templated binary type specification for pointers.
+         * BinaryType template specialization for pointers.
          */
         template <typename T>
         struct IGNITE_IMPORT_EXPORT BinaryType<T*>
@@ -292,7 +292,7 @@ namespace ignite
             /**
              * Get NULL value for the given binary type.
              *
-             * @param dst Null value for the type.
+             * @param dst NULL value for the type.
              */
             static void GetNull(T*& dst)
             {
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h 
b/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h
index 3dc1241..c293935 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h
@@ -307,6 +307,14 @@ namespace ignite
             BinaryStringArrayWriter WriteStringArray(const char* fieldName);
 
             /**
+             * Write binary enum entry.
+             *
+             * @param fieldName Field name.
+             * @param entry Binary enum entry.
+             */
+            void WriteBinaryEnum(const char* fieldName, BinaryEnumEntry entry);
+
+            /**
              * Write NULL value.
              *
              * @param fieldName Field name.
@@ -451,6 +459,20 @@ namespace ignite
             }
 
             /**
+             * Write enum entry.
+             *
+             * @param fieldName Field name.
+             * @param val Binary enum entry.
+             *
+             * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+             */
+            template<typename T>
+            void WriteEnum(const char* fieldName, T val)
+            {
+                impl->WriteEnum(fieldName, val);
+            }
+
+            /**
              * Get raw writer for this reader.
              *
              * @return Raw writer.
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h
index a4275c7..7124170 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h
@@ -158,6 +158,12 @@ namespace ignite
             /** Type: binary object. */
             const int8_t IGNITE_TYPE_BINARY = 27;
 
+            /** Type: Enum. */
+            const int8_t IGNITE_TYPE_ENUM = 28;
+
+            /** Type: Binary Enum. */
+            const int8_t IGNITE_TYPE_BINARY_ENUM = 38;
+
             /** Type: timestamp. */
             const int8_t IGNITE_TYPE_TIMESTAMP = 33;
 
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
index a3b880c..ca9f8b7 100644
--- 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
+++ 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
@@ -30,10 +30,12 @@
 #include "ignite/common/utils.h"
 #include "ignite/binary/binary_consts.h"
 #include "ignite/binary/binary_type.h"
+#include "ignite/binary/binary_enum_entry.h"
 #include "ignite/guid.h"
 #include "ignite/date.h"
 #include "ignite/timestamp.h"
 #include "ignite/time.h"
+#include "ignite/binary/binary_enum.h"
 
 namespace ignite
 {
@@ -65,6 +67,7 @@ namespace ignite
                  * @param rawOff Raw data offset.
                  * @param footerBegin Footer beginning absolute position in 
stream.
                  * @param footerEnd Footer ending absolute position in stream.
+                 * @param schemaType Schema Type.
                  */
                 BinaryReaderImpl(interop::InteropInputStream* stream, 
BinaryIdResolver* idRslvr,
                     int32_t pos, bool usrType, int32_t typeId, int32_t 
hashCode, int32_t len, int32_t rawOff,
@@ -559,10 +562,25 @@ namespace ignite
                 int32_t ReadTimeArray(const char* fieldName, Time* res, const 
int32_t len);
 
                 /**
+                 * Read enum entry.
+                 *
+                 * @return Enum entry.
+                 */
+                ignite::binary::BinaryEnumEntry ReadBinaryEnum();
+
+                /**
+                 * Read enum entry.
+                 *
+                 * @param fieldName Field name.
+                 * @return Enum entry.
+                 */
+                ignite::binary::BinaryEnumEntry ReadBinaryEnum(const char* 
fieldName);
+
+                /**
                  * Read string.
                  *
                  * @param len Expected length of string.
-                 * @param res Array to store data to (should be able to 
acocmodate null-terminator).
+                 * @param res Array to store data to (should be able to 
accomodate null-terminator).
                  * @return Actual amount of elements read. If "len" argument 
is less than actual
                  *     array size or resulting array is set to null, nothing 
will be written
                  *     to resulting array and returned value will contain 
required array length.
@@ -862,6 +880,33 @@ namespace ignite
                 }
 
                 /**
+                 * Read enum value.
+                 *
+                 * @return Enum value.
+                 */
+                template<typename T>
+                T ReadEnum()
+                {
+                    ignite::binary::BinaryEnumEntry entry = ReadBinaryEnum();
+
+                    return DeserializeEnumEntry<T>(entry);
+                }
+
+                /**
+                 * Read enum value.
+                 *
+                 * @param fieldName Field name.
+                 * @return Enum value.
+                 */
+                template<typename T>
+                T ReadEnum(const char* fieldName)
+                {
+                    ignite::binary::BinaryEnumEntry entry = 
ReadBinaryEnum(fieldName);
+
+                    return DeserializeEnumEntry<T>(entry);
+                }
+
+                /**
                  * Try read object.
                  * Reads value, stores it to res and returns true if the value 
is
                  * not null. Otherwise just returns false.
@@ -1105,6 +1150,36 @@ namespace ignite
                 BinaryOffsetType::Type schemaType;
 
                 IGNITE_NO_COPY_ASSIGNMENT(BinaryReaderImpl)
+
+                /**
+                 * Deserialize EnumEntry into user type.
+                 *
+                 * @param entry Entry to deserialize.
+                 * @return User type value.
+                 */
+                template<typename T>
+                T DeserializeEnumEntry(ignite::binary::BinaryEnumEntry entry)
+                {
+                    typedef ignite::binary::BinaryEnum<T> TypeMeta;
+
+                    if (entry.IsNull())
+                    {
+                        T res;
+
+                        TypeMeta::GetNull(res);
+
+                        return res;
+                    }
+
+                    if (entry.GetTypeId() != TypeMeta::GetTypeId())
+                    {
+                        
IGNITE_ERROR_FORMATTED_2(ignite::IgniteError::IGNITE_ERR_BINARY,
+                            "Unexpected type ID during deserialization of the 
enum: ",
+                            "expected", TypeMeta::GetTypeId(), "actual", 
entry.GetTypeId());
+                    }
+
+                    return TypeMeta::FromOrdinal(entry.GetOrdinal());
+                }
                     
                 /**
                  * Internal routine to read Guid array.
@@ -1409,6 +1484,13 @@ namespace ignite
                 void ThrowOnInvalidHeader(int8_t expHdr, int8_t hdr) const;
 
                 /**
+                 * Read enum entry.
+                 *
+                 * @return Enum entry.
+                 */
+                ignite::binary::BinaryEnumEntry ReadBinaryEnumInternal();
+
+                /**
                  * Internal string read routine.
                  *
                  * @param res Resulting array.
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h
index fda9a18..58e5819 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h
@@ -27,6 +27,7 @@
 #include <ignite/timestamp.h>
 #include <ignite/time.h>
 
+#include <ignite/binary/binary_enum_entry.h>
 #include <ignite/binary/binary_type.h>
 
 namespace ignite
@@ -100,7 +101,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.                 
                  */
-                static void ReadInt8Array(interop::InteropInputStream* stream, 
int8_t* res, const int32_t len);
+                static void ReadInt8Array(interop::InteropInputStream* stream, 
int8_t* res, int32_t len);
 
                 /**
                  * Utility method to write signed 8-bit integer array to 
stream.
@@ -109,7 +110,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteInt8Array(interop::InteropOutputStream* 
stream, const int8_t* val, const int32_t len);
+                static void WriteInt8Array(interop::InteropOutputStream* 
stream, const int8_t* val, int32_t len);
 
                 /**
                  * Utility method to read boolean from stream.
@@ -134,7 +135,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadBoolArray(interop::InteropInputStream* stream, 
bool* res, const int32_t len);
+                static void ReadBoolArray(interop::InteropInputStream* stream, 
bool* res, int32_t len);
 
                 /**
                  * Utility method to write bool array to stream.
@@ -143,7 +144,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteBoolArray(interop::InteropOutputStream* 
stream, const bool* val, const int32_t len);
+                static void WriteBoolArray(interop::InteropOutputStream* 
stream, const bool* val, int32_t len);
 
                 /**
                  * Utility method to read signed 16-bit integer from stream.
@@ -188,7 +189,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.                 
                  */
-                static void ReadInt16Array(interop::InteropInputStream* 
stream, int16_t* res, const int32_t len);
+                static void ReadInt16Array(interop::InteropInputStream* 
stream, int16_t* res, int32_t len);
 
                 /**
                  * Utility method to write signed 16-bit integer array to 
stream.
@@ -197,7 +198,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteInt16Array(interop::InteropOutputStream* 
stream, const int16_t* val, const int32_t len);
+                static void WriteInt16Array(interop::InteropOutputStream* 
stream, const int16_t* val, int32_t len);
 
                 /**
                  * Utility method to read unsigned 16-bit integer from stream.
@@ -222,7 +223,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadUInt16Array(interop::InteropInputStream* 
stream, uint16_t* res, const int32_t len);
+                static void ReadUInt16Array(interop::InteropInputStream* 
stream, uint16_t* res, int32_t len);
 
                 /**
                  * Utility method to write unsigned 16-bit integer array to 
stream.
@@ -231,7 +232,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteUInt16Array(interop::InteropOutputStream* 
stream, const uint16_t* val, const int32_t len);
+                static void WriteUInt16Array(interop::InteropOutputStream* 
stream, const uint16_t* val, int32_t len);
 
                 /**
                  * Utility method to read signed 32-bit integer from stream.
@@ -276,7 +277,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadInt32Array(interop::InteropInputStream* 
stream, int32_t* res, const int32_t len);
+                static void ReadInt32Array(interop::InteropInputStream* 
stream, int32_t* res, int32_t len);
 
                 /**
                  * Utility method to write signed 32-bit integer array to 
stream.
@@ -285,7 +286,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteInt32Array(interop::InteropOutputStream* 
stream, const int32_t* val, const int32_t len);
+                static void WriteInt32Array(interop::InteropOutputStream* 
stream, const int32_t* val, int32_t len);
 
                 /**
                  * Utility method to read signed 64-bit integer from stream.
@@ -310,7 +311,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadInt64Array(interop::InteropInputStream* 
stream, int64_t* res, const int32_t len);
+                static void ReadInt64Array(interop::InteropInputStream* 
stream, int64_t* res, int32_t len);
 
                 /**
                  * Utility method to write signed 64-bit integer array to 
stream.
@@ -319,7 +320,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteInt64Array(interop::InteropOutputStream* 
stream, const int64_t* val, const int32_t len);
+                static void WriteInt64Array(interop::InteropOutputStream* 
stream, const int64_t* val, int32_t len);
 
                 /**
                  * Utility method to read float from stream.
@@ -344,7 +345,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadFloatArray(interop::InteropInputStream* 
stream, float* res, const int32_t len);
+                static void ReadFloatArray(interop::InteropInputStream* 
stream, float* res, int32_t len);
 
                 /**
                  * Utility method to write float array to stream.
@@ -353,7 +354,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteFloatArray(interop::InteropOutputStream* 
stream, const float* val, const int32_t len);
+                static void WriteFloatArray(interop::InteropOutputStream* 
stream, const float* val, int32_t len);
 
                 /**
                  * Utility method to read double from stream.
@@ -378,7 +379,7 @@ namespace ignite
                  * @param res Target array.
                  * @param len Array length.
                  */
-                static void ReadDoubleArray(interop::InteropInputStream* 
stream, double* res, const int32_t len);
+                static void ReadDoubleArray(interop::InteropInputStream* 
stream, double* res, int32_t len);
 
                 /**
                  * Utility method to write double array to stream.
@@ -387,13 +388,12 @@ namespace ignite
                  * @param val Value.
                  * @param len Array length.
                  */
-                static void WriteDoubleArray(interop::InteropOutputStream* 
stream, const double* val, const int32_t len);
+                static void WriteDoubleArray(interop::InteropOutputStream* 
stream, const double* val, int32_t len);
 
                 /**
                  * Utility method to read Guid from stream.
                  *
                  * @param stream Stream.
-                 * @param res Value.
                  */
                 static Guid ReadGuid(interop::InteropInputStream* stream);
 
@@ -403,13 +403,12 @@ namespace ignite
                  * @param stream Stream.
                  * @param val Value.
                  */
-                static void WriteGuid(interop::InteropOutputStream* stream, 
const Guid val);
+                static void WriteGuid(interop::InteropOutputStream* stream, 
Guid val);
 
                 /**
                  * Utility method to read Date from stream.
                  *
                  * @param stream Stream.
-                 * @param res Value.
                  */
                 static Date ReadDate(interop::InteropInputStream* stream);
 
@@ -419,7 +418,7 @@ namespace ignite
                  * @param stream Stream.
                  * @param val Value.
                  */
-                static void WriteDate(interop::InteropOutputStream* stream, 
const Date val);
+                static void WriteDate(interop::InteropOutputStream* stream, 
Date val);
 
                 /**
                  * Utility method to read Timestamp from stream.
@@ -435,7 +434,7 @@ namespace ignite
                  * @param stream Stream.
                  * @param val Value.
                  */
-                static void WriteTimestamp(interop::InteropOutputStream* 
stream, const Timestamp val);
+                static void WriteTimestamp(interop::InteropOutputStream* 
stream, Timestamp val);
 
                 /**
                  * Utility method to read Time from stream.
@@ -446,12 +445,41 @@ namespace ignite
                 static Time ReadTime(interop::InteropInputStream* stream);
 
                 /**
-                 * Utility method to write Timestamp to stream.
+                 * Utility method to write Time to stream.
+                 *
+                 * @param stream Stream.
+                 * @param val Value.
+                 */
+                static void WriteTime(interop::InteropOutputStream* stream, 
Time val);
+
+                /**
+                 * Utility method to read BinaryEnumEntry from stream.
+                 *
+                 * @param stream Stream.
+                 * @return Value.
+                 */
+                static ignite::binary::BinaryEnumEntry 
ReadBinaryEnumEntry(interop::InteropInputStream* stream);
+
+                /**
+                 * Utility method to write BinaryEnumEntry to stream.
                  *
                  * @param stream Stream.
                  * @param val Value.
                  */
-                static void WriteTime(interop::InteropOutputStream* stream, 
const Time val);
+                static void WriteBinaryEnumEntry(interop::InteropOutputStream* 
stream,
+                    ignite::binary::BinaryEnumEntry val)
+                {
+                    WriteBinaryEnumEntry(stream, val.GetTypeId(), 
val.GetOrdinal());
+                }
+
+                /**
+                 * Utility method to write Binary Enum Entry to stream.
+                 *
+                 * @param stream Stream.
+                 * @param typeId Type ID.
+                 * @param ordinal Ordinal.
+                 */
+                static void WriteBinaryEnumEntry(interop::InteropOutputStream* 
stream, int32_t typeId, int32_t ordinal);
 
                 /**
                  * Utility method to write string to stream.
@@ -460,7 +488,7 @@ namespace ignite
                  * @param val Value.
                  * @param len Length.
                  */
-                static void WriteString(interop::InteropOutputStream* stream, 
const char* val, const int32_t len);
+                static void WriteString(interop::InteropOutputStream* stream, 
const char* val, int32_t len);
 
                 /**
                  * Get default value for the type.
@@ -551,6 +579,12 @@ namespace ignite
             }
 
             template<>
+            inline ignite::binary::BinaryEnumEntry 
BinaryUtils::GetDefaultValue<ignite::binary::BinaryEnumEntry>()
+            {
+                return ignite::binary::BinaryEnumEntry();
+            }
+
+            template<>
             inline std::string BinaryUtils::GetDefaultValue<std::string>()
             {
                 return std::string();
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
index e6cd487..bc04620 100644
--- 
a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
+++ 
b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
@@ -31,7 +31,6 @@
 #include "ignite/impl/binary/binary_type_manager.h"
 #include "ignite/impl/binary/binary_utils.h"
 #include "ignite/impl/binary/binary_schema.h"
-#include "ignite/impl/binary/binary_type_manager.h"
 #include "ignite/impl/binary/binary_object_impl.h"
 #include "ignite/binary/binary_consts.h"
 #include "ignite/binary/binary_type.h"
@@ -50,6 +49,9 @@ namespace ignite
     {
         namespace binary
         {
+            // Forward declaration.
+            class BinaryTypeManager;
+
             /**
              * Internal implementation of binary reader.
              */
@@ -523,6 +525,21 @@ namespace ignite
                 void WriteStringElement(int32_t id, const char* val, int32_t 
len);
 
                 /**
+                 * Write binary enum entry.
+                 *
+                 * @param entry Binary enum entry.
+                 */
+                void WriteBinaryEnum(ignite::binary::BinaryEnumEntry entry);
+
+                /**
+                 * Write binary enum entry.
+                 *
+                 * @param fieldName Field name.
+                 * @param entry Binary enum entry.
+                 */
+                void WriteBinaryEnum(const char* fieldName, 
ignite::binary::BinaryEnumEntry entry);
+
+                /**
                  * Write NULL value.
                  */
                 void WriteNull();
@@ -542,7 +559,6 @@ namespace ignite
                 /**
                  * Start array write.
                  *
-                 * @param typ Collection type.
                  * @return Session ID.
                  */
                 int32_t WriteArray();
@@ -694,6 +710,55 @@ namespace ignite
                 }
 
                 /**
+                 * Write enum entry.
+                 *
+                 * @param val Binary enum entry.
+                 *
+                 * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+                 */
+                template<typename T>
+                void WriteEnum(T val)
+                {
+                    typedef ignite::binary::BinaryEnum<T> TypeMeta;
+
+                    if (TypeMeta::IsNull(val))
+                    {
+                        WriteNull();
+
+                        return;
+                    }
+
+                    ignite::binary::BinaryEnumEntry 
entry(TypeMeta::GetTypeId(), TypeMeta::GetOrdinal(val));
+
+                    WriteBinaryEnum(entry);
+                }
+
+                /**
+                 * Write enum entry.
+                 *
+                 * @param fieldName Field name.
+                 * @param val Binary enum entry.
+                 *
+                 * @trapam T Enum type. BinaryEnum class template should be 
specialized for the type.
+                 */
+                template<typename T>
+                void WriteEnum(const char* fieldName, T val)
+                {
+                    typedef ignite::binary::BinaryEnum<T> TypeMeta;
+
+                    if (TypeMeta::IsNull(val))
+                    {
+                        WriteNull(fieldName);
+
+                        return;
+                    }
+
+                    ignite::binary::BinaryEnumEntry 
entry(TypeMeta::GetTypeId(), TypeMeta::GetOrdinal(val));
+
+                    WriteBinaryEnum(fieldName, entry);
+                }
+
+                /**
                  * Set raw mode.
                  */
                 void SetRawMode();
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h
 
b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h
index 3652516..2ba318b 100644
--- 
a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h
+++ 
b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h
@@ -199,7 +199,7 @@ namespace ignite
                 /**
                  * Set position.
                  *
-                 * @param Position.
+                 * @param pos Position.
                  */
                 void Position(int32_t pos);
 
@@ -230,7 +230,7 @@ namespace ignite
                 /**
                  * Copy data from the stream shifting it along the way.
                  *
-                 * @param ptr Pointer to data.
+                 * @param dest Pointer to data.
                  * @param off Offset.
                  * @param cnt Amount of data to copy.
                  */
diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj 
b/modules/platforms/cpp/binary/project/vs/binary.vcxproj
index 5b76f06..c973204 100644
--- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj
+++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj
@@ -180,12 +180,14 @@
     <ClInclude Include="..\..\include\ignite\binary\binary.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_consts.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_containers.h" />
+    <ClInclude Include="..\..\include\ignite\binary\binary_enum.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_object.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_raw_reader.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_raw_writer.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_reader.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_type.h" />
     <ClInclude Include="..\..\include\ignite\binary\binary_writer.h" />
+    <ClInclude Include="..\..\include\ignite\binary\binary_enum_entry.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_common.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_field_meta.h" 
/>
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_id_resolver.h" 
/>
diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters 
b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
index 573b5fa..e6528ea 100644
--- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
+++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
@@ -103,6 +103,12 @@
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_type_impl.h">
       <Filter>Code\impl\binary</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ignite\binary\binary_enum_entry.h">
+      <Filter>Code\binary</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\binary\binary_enum.h">
+      <Filter>Code\binary</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\binary\binary_containers.cpp">
diff --git a/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp 
b/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp
index f751685..5f3dcc5 100644
--- a/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp
+++ b/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp
@@ -163,6 +163,11 @@ namespace ignite
             return BinaryStringArrayReader(impl, id, size);
         }
 
+        BinaryEnumEntry BinaryRawReader::ReadBinaryEnum()
+        {
+            return impl->ReadBinaryEnum();
+        }
+
         CollectionType::Type BinaryRawReader::ReadCollectionType()
         {
             return impl->ReadCollectionType();
diff --git a/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp 
b/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp
index f2e94a5..703e1b4 100644
--- a/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp
+++ b/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp
@@ -169,6 +169,11 @@ namespace ignite
             return BinaryStringArrayWriter(impl, id);
         }
 
+        void BinaryRawWriter::WriteBinaryEnum(BinaryEnumEntry entry)
+        {
+            impl->WriteBinaryEnum(entry);
+        }
+
         void BinaryRawWriter::WriteNull()
         {
             impl->WriteNull();
diff --git a/modules/platforms/cpp/binary/src/binary/binary_reader.cpp 
b/modules/platforms/cpp/binary/src/binary/binary_reader.cpp
index 0ba82e6..ee4ba57 100644
--- a/modules/platforms/cpp/binary/src/binary/binary_reader.cpp
+++ b/modules/platforms/cpp/binary/src/binary/binary_reader.cpp
@@ -163,6 +163,11 @@ namespace ignite
             return BinaryStringArrayReader(impl, id, size);
         }
 
+        BinaryEnumEntry BinaryReader::ReadBinaryEnum(const char* fieldName)
+        {
+            return impl->ReadBinaryEnum(fieldName);
+        }
+
         CollectionType::Type BinaryReader::ReadCollectionType(const char* 
fieldName)
         {
             return impl->ReadCollectionType(fieldName);
diff --git a/modules/platforms/cpp/binary/src/binary/binary_writer.cpp 
b/modules/platforms/cpp/binary/src/binary/binary_writer.cpp
index 6c549bb..edce91f 100644
--- a/modules/platforms/cpp/binary/src/binary/binary_writer.cpp
+++ b/modules/platforms/cpp/binary/src/binary/binary_writer.cpp
@@ -169,6 +169,11 @@ namespace ignite
             return BinaryStringArrayWriter(impl, id);
         }
 
+        void BinaryWriter::WriteBinaryEnum(const char* fieldName, 
BinaryEnumEntry entry)
+        {
+            impl->WriteBinaryEnum(fieldName, entry);
+        }
+
         void BinaryWriter::WriteNull(const char* fieldName)
         {
             impl->WriteNull(fieldName);
diff --git 
a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp 
b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
index e3b57ed..7d4d4a1 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
@@ -17,7 +17,8 @@
 
 #include <ignite/ignite_error.h>
 
-#include "ignite/impl/interop/interop.h"
+#include "ignite/impl/interop/interop_memory.h"
+#include "ignite/impl/interop/interop_input_stream.h"
 #include "ignite/impl/interop/interop_stream_position_guard.h"
 #include "ignite/impl/binary/binary_common.h"
 #include "ignite/impl/binary/binary_id_resolver.h"
@@ -375,7 +376,7 @@ namespace ignite
                 return realLen;
             }
 
-            void 
BinaryReaderImpl::ReadTimestampArrayInternal(interop::InteropInputStream* 
stream, Timestamp* res, const int32_t len)
+            void 
BinaryReaderImpl::ReadTimestampArrayInternal(InteropInputStream* stream, 
Timestamp* res, const int32_t len)
             {
                 for (int i = 0; i < len; i++)
                     res[i] = ReadNullable<Timestamp>(stream, 
BinaryUtils::ReadTimestamp, IGNITE_TYPE_TIMESTAMP);
@@ -389,7 +390,7 @@ namespace ignite
                 return ReadNullable(stream, BinaryUtils::ReadTime, 
IGNITE_TYPE_TIME);
             }
 
-            int32_t BinaryReaderImpl::ReadTimeArray(Time * res, int32_t len)
+            int32_t BinaryReaderImpl::ReadTimeArray(Time* res, int32_t len)
             {
                 CheckRawMode(true);
                 CheckSingleMode(true);
@@ -397,7 +398,7 @@ namespace ignite
                 return ReadArrayInternal<Time>(res, len, stream, 
ReadTimeArrayInternal, IGNITE_TYPE_ARRAY_TIME);
             }
 
-            Time BinaryReaderImpl::ReadTime(const char * fieldName)
+            Time BinaryReaderImpl::ReadTime(const char* fieldName)
             {
                 CheckRawMode(false);
                 CheckSingleMode(true);
@@ -413,7 +414,7 @@ namespace ignite
                 return ReadNullable(stream, BinaryUtils::ReadTime, 
IGNITE_TYPE_TIME);
             }
 
-            int32_t BinaryReaderImpl::ReadTimeArray(const char * fieldName, 
Time * res, const int32_t len)
+            int32_t BinaryReaderImpl::ReadTimeArray(const char* fieldName, 
Time* res, const int32_t len)
             {
                 CheckRawMode(false);
                 CheckSingleMode(true);
@@ -431,12 +432,49 @@ namespace ignite
                 return realLen;
             }
 
-            void 
BinaryReaderImpl::ReadTimeArrayInternal(interop::InteropInputStream* stream, 
Time* res, const int32_t len)
+            void BinaryReaderImpl::ReadTimeArrayInternal(InteropInputStream* 
stream, Time* res, const int32_t len)
             {
                 for (int i = 0; i < len; i++)
                     res[i] = ReadNullable<Time>(stream, BinaryUtils::ReadTime, 
IGNITE_TYPE_TIME);
             }
 
+            BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnum()
+            {
+                CheckRawMode(true);
+                CheckSingleMode(true);
+
+                return ReadBinaryEnumInternal();
+            }
+
+            BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnum(const char* 
fieldName)
+            {
+                CheckRawMode(false);
+                CheckSingleMode(true);
+
+                int32_t fieldId = idRslvr->GetFieldId(typeId, fieldName);
+                int32_t fieldPos = FindField(fieldId);
+
+                if (fieldPos <= 0)
+                    return BinaryEnumEntry();
+
+                stream->Position(fieldPos);
+
+                return ReadBinaryEnumInternal();
+            }
+
+            BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnumInternal()
+            {
+                int8_t hdr = stream->ReadInt8();
+
+                if (hdr == IGNITE_TYPE_ENUM || hdr == IGNITE_TYPE_BINARY_ENUM)
+                    return BinaryUtils::ReadBinaryEnumEntry(stream);
+
+                if (hdr != IGNITE_HDR_NULL)
+                    ThrowOnInvalidHeader(IGNITE_TYPE_ENUM, hdr);
+
+                return BinaryUtils::GetDefaultValue<BinaryEnumEntry>();
+            }
+
             int32_t BinaryReaderImpl::ReadString(char* res, const int32_t len)
             {
                 CheckRawMode(true);
@@ -549,7 +587,8 @@ namespace ignite
 
                     return realLen;
                 }
-                else if (hdr != IGNITE_HDR_NULL)
+
+                if (hdr != IGNITE_HDR_NULL)
                     ThrowOnInvalidHeader(IGNITE_TYPE_STRING, hdr);
 
                 return -1;
@@ -879,21 +918,20 @@ namespace ignite
             }
 
             template <typename T>
-            T BinaryReaderImpl::ReadTopObject0(const int8_t expHdr, 
T(*func)(ignite::impl::interop::InteropInputStream*))
+            T BinaryReaderImpl::ReadTopObject0(const int8_t expHdr, 
T(*func)(InteropInputStream*))
             {
                 int8_t typeId = stream->ReadInt8();
 
                 if (typeId == expHdr)
                     return func(stream);
-                else if (typeId == IGNITE_HDR_NULL)
+
+                if (typeId == IGNITE_HDR_NULL)
                     return BinaryUtils::GetDefaultValue<T>();
-                else
-                {
-                    int32_t pos = stream->Position() - 1;
 
-                    IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY,
-                        "Invalid header", "position", pos, "expected", 
(int)expHdr, "actual", (int)typeId)
-                }
+                int32_t pos = stream->Position() - 1;
+
+                IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY,
+                    "Invalid header", "position", pos, "expected", 
(int)expHdr, "actual", (int)typeId)
             }
 
             InteropInputStream* BinaryReaderImpl::GetStream()
@@ -992,23 +1030,18 @@ namespace ignite
 
                         return elemId;
                     }
-                    else
-                    {
-                        *size = 0;
 
-                        return ++elemIdGen;
-                    }
-                }
-                else if (hdr == IGNITE_HDR_NULL) {
-                    *size = -1;
+                    *size = 0;
 
                     return ++elemIdGen;
                 }
-                else {
+
+                if (hdr != IGNITE_HDR_NULL)
                     ThrowOnInvalidHeader(expHdr, hdr);
 
-                    return 0;
-                }
+                *size = -1;
+
+                return ++elemIdGen;
             }
 
             void BinaryReaderImpl::CheckSession(int32_t expSes) const
diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp 
b/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
index a583128..59b2fa1 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
@@ -24,6 +24,7 @@
 
 using namespace ignite::impl::interop;
 using namespace ignite::impl::binary;
+using namespace ignite::binary;
 
 namespace
 {
@@ -108,7 +109,7 @@ namespace ignite
                 return ReadPrimitive<int8_t>(mem, pos);
             }
 
-            int8_t BinaryUtils::UnsafeReadInt8(interop::InteropMemory& mem, 
int32_t pos)
+            int8_t BinaryUtils::UnsafeReadInt8(InteropMemory& mem, int32_t pos)
             {
                 return UnsafeReadPrimitive<int8_t>(mem, pos);
             }
@@ -153,12 +154,12 @@ namespace ignite
                 return stream->ReadInt16();
             }
 
-            int16_t BinaryUtils::ReadInt16(interop::InteropMemory& mem, 
int32_t pos)
+            int16_t BinaryUtils::ReadInt16(InteropMemory& mem, int32_t pos)
             {
                 return ReadPrimitive<int16_t>(mem, pos);
             }
 
-            int16_t BinaryUtils::UnsafeReadInt16(interop::InteropMemory& mem, 
int32_t pos)
+            int16_t BinaryUtils::UnsafeReadInt16(InteropMemory& mem, int32_t 
pos)
             {
                 return UnsafeReadPrimitive<int16_t>(mem, pos);
             }
@@ -203,12 +204,12 @@ namespace ignite
                 return stream->ReadInt32();
             }
 
-            int32_t BinaryUtils::ReadInt32(interop::InteropMemory& mem, 
int32_t pos)
+            int32_t BinaryUtils::ReadInt32(InteropMemory& mem, int32_t pos)
             {
                 return ReadPrimitive<int32_t>(mem, pos);
             }
 
-            int32_t BinaryUtils::UnsafeReadInt32(interop::InteropMemory& mem, 
int32_t pos)
+            int32_t BinaryUtils::UnsafeReadInt32(InteropMemory& mem, int32_t 
pos)
             {
                 return UnsafeReadPrimitive<int32_t>(mem, pos);
             }
@@ -288,7 +289,7 @@ namespace ignite
                 stream->WriteDoubleArray(val, len);
             }
 
-            Guid BinaryUtils::ReadGuid(interop::InteropInputStream* stream)
+            Guid BinaryUtils::ReadGuid(InteropInputStream* stream)
             {
                 int64_t most = stream->ReadInt64();
                 int64_t least = stream->ReadInt64();
@@ -296,25 +297,25 @@ namespace ignite
                 return Guid(most, least);
             }
 
-            void BinaryUtils::WriteGuid(interop::InteropOutputStream* stream, 
const Guid val)
+            void BinaryUtils::WriteGuid(InteropOutputStream* stream, const 
Guid val)
             {
                 stream->WriteInt64(val.GetMostSignificantBits());
                 stream->WriteInt64(val.GetLeastSignificantBits());
             }
 
-            Date BinaryUtils::ReadDate(interop::InteropInputStream * stream)
+            Date BinaryUtils::ReadDate(InteropInputStream * stream)
             {
                 int64_t milliseconds = stream->ReadInt64();
 
                 return Date(milliseconds);
             }
 
-            void BinaryUtils::WriteDate(interop::InteropOutputStream* stream, 
const Date val)
+            void BinaryUtils::WriteDate(InteropOutputStream* stream, const 
Date val)
             {
                 stream->WriteInt64(val.GetMilliseconds());
             }
 
-            Timestamp BinaryUtils::ReadTimestamp(interop::InteropInputStream* 
stream)
+            Timestamp BinaryUtils::ReadTimestamp(InteropInputStream* stream)
             {
                 int64_t milliseconds = stream->ReadInt64();
                 int32_t nanoseconds = stream->ReadInt32();
@@ -322,25 +323,39 @@ namespace ignite
                 return Timestamp(milliseconds / 1000, (milliseconds % 1000) * 
1000000 + nanoseconds);
             }
 
-            void BinaryUtils::WriteTimestamp(interop::InteropOutputStream* 
stream, const Timestamp val)
+            void BinaryUtils::WriteTimestamp(InteropOutputStream* stream, 
const Timestamp val)
             {
                 stream->WriteInt64(val.GetSeconds() * 1000 + 
val.GetSecondFraction() / 1000000);
                 stream->WriteInt32(val.GetSecondFraction() % 1000000);
             }
 
-            Time BinaryUtils::ReadTime(interop::InteropInputStream* stream)
+            Time BinaryUtils::ReadTime(InteropInputStream* stream)
             {
                 int64_t ms = stream->ReadInt64();
 
                 return Time(ms);
             }
 
-            void BinaryUtils::WriteTime(interop::InteropOutputStream* stream, 
const Time val)
+            void BinaryUtils::WriteTime(InteropOutputStream* stream, const 
Time val)
             {
                 stream->WriteInt64(val.GetMilliseconds());
             }
 
-            void BinaryUtils::WriteString(interop::InteropOutputStream* 
stream, const char* val, const int32_t len)
+            BinaryEnumEntry 
BinaryUtils::ReadBinaryEnumEntry(InteropInputStream* stream)
+            {
+                int32_t typeId = stream->ReadInt32();
+                int32_t ordinal = stream->ReadInt32();
+
+                return BinaryEnumEntry(typeId, ordinal);
+            }
+
+            void BinaryUtils::WriteBinaryEnumEntry(InteropOutputStream * 
stream, int32_t typeId, int32_t ordinal)
+            {
+                stream->WriteInt32(typeId);
+                stream->WriteInt32(ordinal);
+            }
+
+            void BinaryUtils::WriteString(InteropOutputStream* stream, const 
char* val, const int32_t len)
             {
                 stream->WriteInt32(len);
                 stream->WriteInt8Array(reinterpret_cast<const int8_t*>(val), 
len);
diff --git 
a/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp 
b/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp
index 51be3a0..49197ec 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp
@@ -521,6 +521,27 @@ namespace ignite
                 elemCnt++;
             }
 
+            void BinaryWriterImpl::WriteBinaryEnum(BinaryEnumEntry entry)
+            {
+                CheckRawMode(true);
+                CheckSingleMode(true);
+
+                stream->WriteInt8(IGNITE_TYPE_ENUM);
+
+                BinaryUtils::WriteBinaryEnumEntry(stream, entry);
+            }
+
+            void BinaryWriterImpl::WriteBinaryEnum(const char* fieldName, 
BinaryEnumEntry entry)
+            {
+                CheckRawMode(false);
+                CheckSingleMode(true);
+
+                WriteFieldId(fieldName, IGNITE_TYPE_ENUM);
+                stream->WriteInt8(IGNITE_TYPE_ENUM);
+
+                BinaryUtils::WriteBinaryEnumEntry(stream, entry);
+            }
+
             void BinaryWriterImpl::WriteNull()
             {
                 CheckRawMode(true);
diff --git a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h 
b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h
index 51aeff0..a509e22 100644
--- a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h
+++ b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h
@@ -130,6 +130,27 @@ namespace ignite_test
                     return new DummyIdResolver();
                 }
             };
+
+            struct TestEnum
+            {
+                enum Type
+                {
+                    TEST_ZERO,
+
+                    TEST_NON_ZERO,
+
+                    TEST_NEGATIVE_42 = -42,
+
+                    TEST_SOME_BIG = 1241267,
+                };
+            };
+
+            struct TypeWithEnumField
+            {
+                int32_t i32Field;
+                TestEnum::Type enumField;
+                std::string strField;
+            };
         }
     }
 }
@@ -300,6 +321,43 @@ namespace ignite
                 dst.val2 = rawReader.ReadInt32();
             }
         };
+
+        template<>
+        struct BinaryEnum<gt::TestEnum::Type> : 
BinaryEnumDefaultAll<gt::TestEnum::Type>
+        {
+            /**
+             * Get binary object type name.
+             *
+             * @param dst Output type name.
+             */
+            static void GetTypeName(std::string& dst)
+            {
+                dst = "TestEnum";
+            }
+        };
+
+        template<>
+        struct BinaryType<gt::TypeWithEnumField> : 
BinaryTypeDefaultAll<gt::TypeWithEnumField>
+        {
+            static void GetTypeName(std::string& dst)
+            {
+                dst = "TypeWithEnumField";
+            }
+
+            static void Write(BinaryWriter& writer, const 
gt::TypeWithEnumField& obj)
+            {
+                writer.WriteInt32("i32Field", obj.i32Field);
+                writer.WriteEnum("enumField", obj.enumField);
+                writer.WriteString("strField", obj.strField);
+            }
+
+            static void Read(BinaryReader& reader, gt::TypeWithEnumField& dst)
+            {
+                dst.i32Field = reader.ReadInt32("i32Field");
+                dst.enumField = 
reader.ReadEnum<gt::TestEnum::Type>("enumField");
+                dst.strField = reader.ReadString("strField");
+            }
+        };
     }
 }
 
diff --git a/modules/platforms/cpp/core-test/src/binary_object_test.cpp 
b/modules/platforms/cpp/core-test/src/binary_object_test.cpp
index 3abd26a..37a3a0d 100644
--- a/modules/platforms/cpp/core-test/src/binary_object_test.cpp
+++ b/modules/platforms/cpp/core-test/src/binary_object_test.cpp
@@ -21,6 +21,9 @@
 #include <ignite/common/fixed_size_array.h>
 #include <ignite/binary/binary_object.h>
 #include <ignite/binary/binary_writer.h>
+#include <ignite/binary/binary_enum.h>
+#include <ignite/binary/binary_enum_entry.h>
+#include <ignite/ignition.h>
 
 #include "ignite/binary_test_defs.h"
 #include "ignite/test_type.h"
@@ -389,4 +392,118 @@ BOOST_AUTO_TEST_CASE(GetEnumValueInvalid)
     BOOST_CHECK_THROW(binObj.GetEnumValue(), IgniteError);
 }
 
+void CheckBinaryEnumEntry(int32_t typeId, int32_t ordinal)
+{
+    InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    BinaryEnumEntry original(typeId, ordinal);
+
+    writer.WriteBinaryEnum(original);
+
+    outStream.Synchronize();
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    BinaryEnumEntry result = reader.ReadBinaryEnum();
+
+    if (original.IsNull())
+    {
+        BOOST_CHECK(result.IsNull());
+
+        return;
+    }
+
+    BOOST_CHECK_EQUAL(original.GetTypeId(), result.GetTypeId());
+    BOOST_CHECK_EQUAL(original.GetOrdinal(), result.GetOrdinal());
+}
+
+BOOST_AUTO_TEST_CASE(ReadWriteBinaryEnum)
+{
+    CheckBinaryEnumEntry(1234567, 42);
+    CheckBinaryEnumEntry(1234567, 1);
+    CheckBinaryEnumEntry(1, 1);
+    CheckBinaryEnumEntry(6754, 0);
+    CheckBinaryEnumEntry(0, 0);
+    CheckBinaryEnumEntry(0, 1);
+}
+
+template<typename T>
+void CheckUserEnum(T val)
+{
+    InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    writer.WriteEnum(val);
+
+    outStream.Synchronize();
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    T result = reader.ReadEnum<T>();
+
+    BOOST_CHECK_EQUAL(val, result);
+}
+
+BOOST_AUTO_TEST_CASE(ReadWriteUserEnum)
+{
+    CheckUserEnum(TestEnum::TEST_ZERO);
+    CheckUserEnum(TestEnum::TEST_NON_ZERO);
+    CheckUserEnum(TestEnum::TEST_NEGATIVE_42);
+    CheckUserEnum(TestEnum::TEST_SOME_BIG);
+}
+
+template<typename T>
+void CheckUserEnumPtr(T val)
+{
+    InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    writer.WriteEnum(&val);
+
+    outStream.Synchronize();
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    T* result = reader.ReadEnum<T*>();
+
+    BOOST_CHECK_EQUAL(val, *result);
+
+    delete result;
+}
+
+BOOST_AUTO_TEST_CASE(ReadWriteUserEnumPtr)
+{
+    CheckUserEnumPtr(TestEnum::TEST_ZERO);
+    CheckUserEnumPtr(TestEnum::TEST_NON_ZERO);
+    CheckUserEnumPtr(TestEnum::TEST_NEGATIVE_42);
+    CheckUserEnumPtr(TestEnum::TEST_SOME_BIG);
+}
+
+BOOST_AUTO_TEST_CASE(ReadWriteUserEnumNullPtr)
+{
+    InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    writer.WriteEnum<TestEnum::Type*>(0);
+
+    outStream.Synchronize();
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    TestEnum::Type* result = reader.ReadEnum<TestEnum::Type*>();
+
+    BOOST_CHECK(result == 0);
+
+    delete result;
+}
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/platforms/cpp/core-test/src/cache_test.cpp 
b/modules/platforms/cpp/core-test/src/cache_test.cpp
index db09940..ff30f93 100644
--- a/modules/platforms/cpp/core-test/src/cache_test.cpp
+++ b/modules/platforms/cpp/core-test/src/cache_test.cpp
@@ -21,6 +21,7 @@
 #include "ignite/ignite.h"
 #include "ignite/ignition.h"
 #include "ignite/test_utils.h"
+#include "ignite/binary_test_defs.h"
 
 using namespace ignite;
 using namespace boost::unit_test;
@@ -97,6 +98,29 @@ struct CacheTestSuiteFixture
 #endif
     }
 
+    void PutGetStructWithEnumField(int32_t i32Field, 
ignite_test::core::binary::TestEnum::Type enumField,
+        const std::string& strField)
+    {
+        typedef ignite_test::core::binary::TypeWithEnumField TypeWithEnumField;
+
+        TypeWithEnumField val;
+        val.i32Field = i32Field;
+        val.enumField = enumField;
+        val.strField = strField;
+
+        cache::Cache<int, TypeWithEnumField> cache = 
grid0.GetOrCreateCache<int, TypeWithEnumField>("PutGetStructWithEnumField");
+
+        BOOST_TEST_CHECKPOINT("Putting value into the cache");
+        cache.Put(i32Field, val);
+
+        BOOST_TEST_CHECKPOINT("Getting value from the cache");
+        TypeWithEnumField res = cache.Get(i32Field);
+
+        BOOST_CHECK_EQUAL(val.i32Field, res.i32Field);
+        BOOST_CHECK_EQUAL(val.enumField, res.enumField);
+        BOOST_CHECK_EQUAL(val.strField, res.strField);
+    }
+
     /*
      * Destructor.
      */
@@ -203,7 +227,7 @@ BOOST_AUTO_TEST_CASE(TestPutAll)
 
     for (int i = 0; i < 100; i++)
         map[i] = i + 1;
-    
+
     cache::Cache<int, int> cache = Cache();
 
     cache.PutAll(map);
@@ -259,7 +283,7 @@ BOOST_AUTO_TEST_CASE(TestGet)
 
     BOOST_REQUIRE(1 == cache.Get(1));
     BOOST_REQUIRE(2 == cache.Get(2));
-    
+
     BOOST_REQUIRE(0 == cache.Get(3));
 }
 
@@ -268,7 +292,7 @@ BOOST_AUTO_TEST_CASE(TestGetAll)
     cache::Cache<int, int> cache = Cache();
 
     int keys[] = { 1, 2, 3, 4, 5 };
-    
+
     std::set<int> keySet (keys, keys + 5);
 
     for (int i = 0; i < static_cast<int>(keySet.size()); i++)
@@ -366,14 +390,14 @@ BOOST_AUTO_TEST_CASE(TestContainsKey)
     BOOST_REQUIRE(true == cache.ContainsKey(1));
 
     BOOST_REQUIRE(true == cache.Remove(1));
-    
+
     BOOST_REQUIRE(false == cache.ContainsKey(1));
 }
 
 BOOST_AUTO_TEST_CASE(TestContainsKeys)
 {
     cache::Cache<int, int> cache = Cache();
-    
+
     int keys[] = { 1, 2 };
 
     std::set<int> keySet(keys, keys + 2);
@@ -382,7 +406,7 @@ BOOST_AUTO_TEST_CASE(TestContainsKeys)
 
     cache.Put(1, 1);
     cache.Put(2, 2);
-    
+
     BOOST_REQUIRE(true == cache.ContainsKeys(keySet));
 
     cache.Remove(1);
@@ -691,4 +715,18 @@ BOOST_AUTO_TEST_CASE(TestGetBigString)
     BOOST_REQUIRE(longStr == cache.Get(5));
 }
 
+BOOST_AUTO_TEST_CASE(TestPutGetStructWithEnumField)
+{
+    typedef ignite_test::core::binary::TestEnum TestEnum;
+
+    PutGetStructWithEnumField(0, TestEnum::TEST_ZERO, "");
+    PutGetStructWithEnumField(1, TestEnum::TEST_ZERO, "");
+    PutGetStructWithEnumField(0, TestEnum::TEST_NON_ZERO, "");
+    PutGetStructWithEnumField(0, TestEnum::TEST_ZERO, "Lorem ipsum");
+    PutGetStructWithEnumField(1, TestEnum::TEST_NON_ZERO, "Lorem ipsum");
+
+    PutGetStructWithEnumField(13, TestEnum::TEST_NEGATIVE_42, "hishib");
+    PutGetStructWithEnumField(1337, TestEnum::TEST_SOME_BIG, "Some test 
value");
+}
+
 BOOST_AUTO_TEST_SUITE_END()

Reply via email to