void updateTreeWithRemovedNode(
        Process::MessageNode& rootNode,
        const State::Address& addr)
{
    // Find the message node
    Process::MessageNode* node_ptr = Device::try_getNodeFromString(rootNode, stringList(addr));

    if(node_ptr)
    {
        auto& node = *node_ptr;
        // Recursively set the user value to nil.
        rec_removeUserValue(node);

        // If it is empty, delete it
        rec_cleanup(node);


        if(node.values.previousProcessValues.isEmpty()
        && node.values.followingProcessValues.isEmpty()
        && node.childCount() == 0)
        {
            rec_delete(node);
        }
    }
}
static void rec_delete(Process::MessageNode& node)
{
    if(node.childCount() == 0)
    {
        // kthxbai
        auto parent = node.parent();
        if(parent)
        {
            auto it = std::find_if(parent->begin(), parent->end(), [&] (const auto& other) { return &node == &other; });
            if(it != parent->end())
            {
                parent->erase(it);
                rec_delete(*parent);
            }
        }
    }
}
void updateTreeWithRemovedUserMessage(
        Process::MessageNode& rootNode,
        const State::Address& addr)
{
    // Find the message node
    Process::MessageNode* node = Device::try_getNodeFromString(rootNode, stringList(addr));

    if(node)
    {
        node->values.userValue = State::OptionalValue{};

        // If it is empty, delete it.
        if(node->values.previousProcessValues.isEmpty()
        && node->values.followingProcessValues.isEmpty()
        && node->childCount() == 0)
        {
            rec_delete(*node);
        }
    }
}
/**
 * Destructor for singly-linked list
 */
List::~List()
{
    rec_delete(head);
}
/**
 * Recursive helper function to deallocate list
 */
void rec_delete(Node * nextNode) {
    if (nullptr == nextNode) return;
    rec_delete(nextNode->next);
    delete nextNode;
}