Add support for binary values

Change-Id: I0ebc7d49590e3bffc449a781822e4d6bf423f331
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index fe2fa84..55b6ccd 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -14,6 +14,13 @@
 {
 }
 
+binary_::binary_() = default;
+
+binary_::binary_(const std::string& value)
+    : m_value(value)
+{
+}
+
 bool set_::operator==(const set_& b) const
 {
     return this->m_path == b.m_path && this->m_data == b.m_data;
@@ -29,6 +36,11 @@
     return this->m_path == b.m_path && this->m_options == b.m_options;
 }
 
+bool binary_::operator==(const binary_& b) const
+{
+    return this->m_value == b.m_value;
+}
+
 bool enum_::operator==(const enum_& b) const
 {
     return this->m_value == b.m_value;
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index acda9fa..634a190 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -193,8 +193,9 @@
 BOOST_FUSION_ADAPT_STRUCT(cd_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(create_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(delete_, m_path)
-BOOST_FUSION_ADAPT_STRUCT(enum_, m_value)
 BOOST_FUSION_ADAPT_STRUCT(set_, m_path, m_data)
+BOOST_FUSION_ADAPT_STRUCT(enum_, m_value)
+BOOST_FUSION_ADAPT_STRUCT(binary_, m_value)
 BOOST_FUSION_ADAPT_STRUCT(commit_)
 BOOST_FUSION_ADAPT_STRUCT(help_, m_cmd)
 BOOST_FUSION_ADAPT_STRUCT(discard_)
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 96ccc53..a34f6c4 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -445,6 +445,15 @@
     }
 };
 
+struct leaf_data_binary_data_class;
+
+struct leaf_data_binary_class : leaf_data_base_class {
+    leaf_data_binary_class()
+        : leaf_data_base_class(yang::LeafDataTypes::Binary)
+    {
+    }
+};
+
 struct set_class {
     template <typename Iterator, typename Exception, typename Context>
     x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
diff --git a/src/ast_values.hpp b/src/ast_values.hpp
index 369a73e..b9053c0 100644
--- a/src/ast_values.hpp
+++ b/src/ast_values.hpp
@@ -16,7 +16,15 @@
     std::string m_value;
 };
 
+struct binary_ {
+    binary_();
+    binary_(const std::string& value);
+    bool operator==(const binary_& b) const;
+    std::string m_value;
+};
+
 using leaf_data_ = boost::variant<enum_,
+                                  binary_,
                                   double,
                                   bool,
                                   int32_t,
diff --git a/src/grammars.hpp b/src/grammars.hpp
index b1c1b03..5878053 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -42,6 +42,8 @@
 x3::rule<leaf_data_int_class, int32_t> const leaf_data_int = "leaf_data_int";
 x3::rule<leaf_data_uint_class, uint32_t> const leaf_data_uint = "leaf_data_uint";
 x3::rule<leaf_data_string_class, std::string> const leaf_data_string = "leaf_data_string";
+x3::rule<leaf_data_binary_data_class, std::string> const leaf_data_binary_data = "leaf_data_binary_data";
+x3::rule<leaf_data_binary_class, binary_> const leaf_data_binary = "leaf_data_binary";
 
 x3::rule<discard_class, discard_> const discard = "discard";
 x3::rule<ls_class, ls_> const ls = "ls";
@@ -202,6 +204,13 @@
 auto const leaf_data_string_def =
     *char_;
 
+// This intermediate rule is neccessary for coercing to std::string.
+auto const leaf_data_binary_data_def =
+    +(x3::alnum | char_('+') | char_('/')) >> -char_('=') >> -char_('=');
+
+auto const leaf_data_binary_def =
+    leaf_data_binary_data;
+
 auto const leaf_data_def =
 x3::expect[
     leaf_data_enum |
@@ -209,6 +218,7 @@
     leaf_data_bool |
     leaf_data_int |
     leaf_data_uint |
+    leaf_data_binary |
     leaf_data_string];
 
 struct ls_options_table : x3::symbols<LsOption> {
@@ -298,6 +308,8 @@
 BOOST_SPIRIT_DEFINE(leaf_data_int)
 BOOST_SPIRIT_DEFINE(leaf_data_uint)
 BOOST_SPIRIT_DEFINE(leaf_data_string)
+BOOST_SPIRIT_DEFINE(leaf_data_binary_data)
+BOOST_SPIRIT_DEFINE(leaf_data_binary)
 BOOST_SPIRIT_DEFINE(initializePath)
 BOOST_SPIRIT_DEFINE(set)
 BOOST_SPIRIT_DEFINE(commit)
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 5d22b6b..aff5bcc 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -15,6 +15,12 @@
     {
         return data.m_value;
     }
+
+    std::string operator()(const binary_& data) const
+    {
+        return data.m_value;
+    }
+
     template <typename T>
     std::string operator()(const T& data) const
     {
diff --git a/src/schema.hpp b/src/schema.hpp
index c55e659..aaeb846 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -28,6 +28,7 @@
     Int,
     Uint,
     Enum,
+    Binary,
 };
 
 struct container {
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index 5c80bbc..a6388db 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -43,6 +43,11 @@
         return std::make_shared<sysrepo::Val>(value.m_value.c_str(), SR_ENUM_T);
     }
 
+    sysrepo::S_Val operator()(const binary_& value) const
+    {
+        return std::make_shared<sysrepo::Val>(value.m_value.c_str(), SR_BINARY_T);
+    }
+
     sysrepo::S_Val operator()(const std::string& value) const
     {
         return std::make_shared<sysrepo::Val>(value.c_str());
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 28ef7d6..f6e0eea 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -204,6 +204,8 @@
         return yang::LeafDataTypes::Uint;
     case LY_TYPE_ENUM:
         return yang::LeafDataTypes::Enum;
+    case LY_TYPE_BINARY:
+        return yang::LeafDataTypes::Binary;
     default:
         throw UnsupportedYangTypeException("the type of "s + fullNodeName(location, node) + " is not supported");
     }