Add info about default values to describe

Change-Id: I9919e0d366b56ac17e7b606aa5aa0ae048b447c3
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index f3fde9e..d01cb1d 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -121,6 +121,10 @@
         if (m_datastore.schema()->leafIsKey(path)) {
             ss << " (key)";
         }
+
+        if (auto defaultValue = m_datastore.schema()->defaultValue(path)) {
+            ss << " default: " << leafDataToString(*defaultValue);
+        }
         break;
     }
     case yang::NodeTypes::List:
diff --git a/src/schema.hpp b/src/schema.hpp
index b8baf34..49fc5db 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -55,6 +55,7 @@
     virtual bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const = 0;
     virtual bool leafIsKey(const std::string& leafPath) const = 0;
     virtual bool isConfig(const std::string& path) const = 0;
+    virtual std::optional<std::string> defaultValue(const std::string& leafPath) const = 0;
     virtual const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const = 0;
     virtual yang::TypeInfo leafType(const schemaPath_& location, const ModuleNodePair& node) const = 0;
     virtual yang::TypeInfo leafType(const std::string& path) const = 0;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index 50a6370..dfb12e8 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -221,3 +221,8 @@
 {
     throw std::runtime_error{"Internal error: StaticSchema::isConfigLeaf(std::string) not implemented. The tests should not have called this overload."};
 }
+
+std::optional<std::string> StaticSchema::defaultValue([[maybe_unused]] const std::string& leafPath) const
+{
+    throw std::runtime_error{"Internal error: StaticSchema::defaultValue(std::string) not implemented. The tests should not have called this overload."};
+}
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index 554d83a..0d2bdff 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -51,6 +51,7 @@
     bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const override;
     bool leafIsKey(const std::string& leafPath) const override;
     bool isConfig(const std::string& leafPath) const override;
+    std::optional<std::string> defaultValue(const std::string& leafPath) const override;
     const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
     yang::TypeInfo leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
     yang::TypeInfo leafType(const std::string& path) const override;
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 046bfcd..6290429 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -460,3 +460,20 @@
 {
     return getSchemaNode(path.c_str())->flags() & LYS_CONFIG_W;
 }
+
+std::optional<std::string> YangSchema::defaultValue(const std::string& leafPath) const
+{
+    libyang::Schema_Node_Leaf leaf(getSchemaNode(leafPath));
+
+    if (auto leafDefault = leaf.dflt()) {
+        return leafDefault;
+    }
+
+    for (auto type = leaf.type()->der(); type != nullptr; type = type->type()->der()) {
+        if (auto defaultValue = type->dflt()) {
+            return defaultValue;
+        }
+    }
+
+    return std::nullopt;
+}
diff --git a/src/yang_schema.hpp b/src/yang_schema.hpp
index a1b7832..c62ed20 100644
--- a/src/yang_schema.hpp
+++ b/src/yang_schema.hpp
@@ -37,6 +37,7 @@
     bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const override;
     bool leafIsKey(const std::string& leafPath) const override;
     bool isConfig(const std::string& path) const override;
+    std::optional<std::string> defaultValue(const std::string& leafPath) const override;
     const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
     yang::TypeInfo leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
     yang::TypeInfo leafType(const std::string& path) const override;
diff --git a/tests/yang.cpp b/tests/yang.cpp
index a458909..598f115 100644
--- a/tests/yang.cpp
+++ b/tests/yang.cpp
@@ -130,6 +130,7 @@
 
     leaf leafUint64 {
         type uint64;
+        default 9001;
     }
 
     leaf leafEnum {
@@ -146,6 +147,7 @@
             enum data;
             enum coze;
         }
+        default data;
     }
 
     typedef enumTypedefRestricted {
@@ -939,6 +941,13 @@
             REQUIRE_FALSE(ys.isConfig("/example-schema:systemStats/upTime"));
         }
 
+        SECTION("defaultValue")
+        {
+            REQUIRE(ys.defaultValue("/example-schema:leafUint64") == "9001");
+            REQUIRE(ys.defaultValue("/example-schema:leafEnumTypedefRestricted") == "data");
+            REQUIRE(ys.defaultValue("/example-schema:leafInt32") == std::nullopt);
+        }
+
         SECTION("moduleNodes")
         {
             std::string module;