Skip to content

Commit

Permalink
Add isInitialized to nix::Value
Browse files Browse the repository at this point in the history
Add a method to check if a value has been initialized. This helps avoid
segfaults when calling `type()`.
Useful in the context of the new C API.

Closes NixOS#10524
  • Loading branch information
jlesquembre committed Apr 18, 2024
1 parent 40499bc commit 0be906b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/libexpr/value.hh
Expand Up @@ -23,6 +23,7 @@ class BindingsBuilder;


typedef enum {
tUnset,
tInt = 1,
tBool,
tString,
Expand Down Expand Up @@ -166,7 +167,7 @@ public:
struct Value
{
private:
InternalType internalType;
InternalType internalType = tUnset;

friend std::string showType(const Value & v);

Expand Down Expand Up @@ -270,6 +271,7 @@ public:
inline ValueType type(bool invalidIsThunk = false) const
{
switch (internalType) {
case tUnset: break;
case tInt: return nInt;
case tBool: return nBool;
case tString: return nString;
Expand All @@ -294,6 +296,11 @@ public:
internalType = newType;
}

inline bool isInitialized()
{
return internalType != tUnset;
}

inline void mkInt(NixInt n)
{
finishValue(tInt, { .integer = n });
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/libexpr/value/value.cc
@@ -0,0 +1,25 @@
#include "value.hh"

#include "tests/libstore.hh"

namespace nix {

class ValueTest : public LibStoreTest
{};

TEST_F(ValueTest, unsetValue)
{
Value unsetValue;
ASSERT_EQ(false, unsetValue.isInitialized());
ASSERT_EQ(nThunk, unsetValue.type(true));
ASSERT_DEATH(unsetValue.type(), "");
}

TEST_F(ValueTest, vInt)
{
Value vInt;
vInt.mkInt(42);
ASSERT_EQ(true, vInt.isInitialized());
}

} // namespace nix

0 comments on commit 0be906b

Please sign in to comment.