 public struct ElementNode: Node {
     public typealias RawType = GumboElement
 
-    public let parent: OpaqueNode?
     public let children: [OpaqueNode]
     public let tag: TagType
     public let attributes: [Attribute]
 
-    public init(rawNode: GumboElement, parent: OpaqueNode?) {
-        self.parent = parent
+    public init(rawNode: GumboElement) {
         self.children = rawNode.children
             .flatMap { $0?.assumingMemoryBound(to: GumboNode.self) }
             .map(mapPointerToStruct)

public struct DocumentNode: Node {
    public typealias RawType = GumboDocument

    public let parent: OpaqueNode?
    public let children: [OpaqueNode]

    public init(rawNode: GumboDocument, parent: OpaqueNode?) {
        self.parent = parent
        self.children = rawNode.children
            .flatMap { $0?.assumingMemoryBound(to: GumboNode.self) }
            .map(mapPointerToStruct)

import CGumbo

public protocol OpaqueNode {
}

public protocol Node: OpaqueNode {
    associatedtype RawType
    init(rawNode: RawType)
}

fileprivate func mapPointerToStruct(rawNode: UnsafeMutablePointer<GumboNode>) -> OpaqueNode {
    switch rawNode.pointee.type {
    case GUMBO_NODE_DOCUMENT:
        return DocumentNode(rawNode: rawNode.pointee.v.document)
    case GUMBO_NODE_ELEMENT:
        return ElementNode(rawNode: rawNode.pointee.v.element)
    case GUMBO_NODE_TEXT:
        return TextNode(rawNode: rawNode.pointee.v.text)
    default:
        fatalError()
    }
