<commit_before>package rtypes

import (
	"errors"

	"github.com/robloxapi/types"
)

// Instance contains data describing an instance of a particular class. It
// corresponds to the Instance type in Roblox.
type Instance struct {
	ClassName string
	Reference string
	IsService bool

	properties  map[string]types.PropValue
	children    []*Instance
	parent      *Instance
	desc        *RootDesc
	descBlocked bool
	root        bool
}

// NewInstance returns a new Instance of the given class name. Optionally,
// parent sets the Parent of the instance.
func NewInstance(className string, parent *Instance) *Instance {
	inst := &Instance{
		ClassName:  className,
		properties: make(map[string]types.PropValue, 0),
	}
	if parent != nil {
		inst.SetParent(parent)
	}
	return inst
}

// NewDataModel returns a special Instance of the DataModel class, to be used as
// the root of a tree of instances.
func NewDataModel() *Instance {
	return &Instance{
		root:       true,
		ClassName:  "DataModel",
		properties: make(map[string]types.PropValue, 0),
	}
}

// IsDataModel returns whether the instance is a root DataModel.
func (inst *Instance) IsDataModel() bool {
	return inst.root
}

// propRef holds the value of an instance property to be resolved later.
type propRef struct {
	Instance *Instance
	Property string
	Value    *Instance
}

// clone returns a deep copy of the instance while managing references.
func (inst *Instance) clone(refs map[*Instance]*Instance, propRefs *[]propRef) *Instance {
	clone := &Instance{
		ClassName:  inst.ClassName,
		Reference:  inst.Reference,
		IsService:  inst.IsService,
		desc:       inst.desc,
		children:   make([]*Instance, len(inst.children)),
		properties: make(map[string]types.PropValue, len(inst.properties)),
	}
	refs[inst] = clone
	for name, v := range inst.properties {
		switch v := v.(type) {
		case *Instance:
			*propRefs = append(*propRefs, propRef{
				Instance: clone,
				Property: name,
				Value:    v,
			})
			continue
		case types.PropValue:
			clone.properties[name] = v.Copy()
		}
		clone.properties[name] = v
	}
	for i, child := range inst.children {
		c := child.clone(refs, propRefs)
		clone.children[i] = c
		c.parent = clone
	}
	return clone
}

// Clone returns a copy of the instance. Each property and all descendants are
// copied as well. Unlike Roblox's implementation, the Archivable property is
// ignored.
//<commit_msg>Ensure that all fields are copied when cloning instances.<commit_after>package rtypes

import (
	"errors"

	"github.com/robloxapi/types"
)

// Instance contains data describing an instance of a particular class. It
// corresponds to the Instance type in Roblox.
type Instance struct {
	ClassName string
	Reference string
	IsService bool

	properties  map[string]types.PropValue
	children    []*Instance
	parent      *Instance
	desc        *RootDesc
	descBlocked bool
	root        bool
}

// NewInstance returns a new Instance of the given class name. Optionally,
// parent sets the Parent of the instance.
func NewInstance(className string, parent *Instance) *Instance {
	inst := &Instance{
		ClassName:  className,
		properties: make(map[string]types.PropValue, 0),
	}
	if parent != nil {
		inst.SetParent(parent)
	}
	return inst
}

// NewDataModel returns a special Instance of the DataModel class, to be used as
// the root of a tree of instances.
func NewDataModel() *Instance {
	return &Instance{
		root:       true,
		ClassName:  "DataModel",
		properties: make(map[string]types.PropValue, 0),
	}
}

// IsDataModel returns whether the instance is a root DataModel.
func (inst *Instance) IsDataModel() bool {
	return inst.root
}

// propRef holds the value of an instance property to be resolved later.
type propRef struct {
	Instance *Instance
	Property string
	Value    *Instance
}

// clone returns a deep copy of the instance while managing references.
func (inst *Instance) clone(refs map[*Instance]*Instance, propRefs *[]propRef) *Instance {
	c := *inst
	clone := &c
	clone.children = make([]*Instance, len(inst.children))
	clone.properties = make(map[string]types.PropValue, len(inst.properties))
	clone.parent = nil
	refs[inst] = clone
	for name, v := range inst.properties {
		switch v := v.(type) {
		case *Instance:
			*propRefs = append(*propRefs, propRef{
				Instance: clone,
				Property: name,
				Value:    v,
			})
			continue
		case types.PropValue:
			clone.properties[name] = v.Copy()
		}
		clone.properties[name] = v
	}
	for i, child := range inst.children {
		c := child.clone(refs, propRefs)
		clone.children[i] = c
		c.parent = clone
	}
	return clone
}

// Clone returns a copy of the instance. Each property and all descendants are
// copied as well. Unlike Roblox's implementation, the Archivable property is
// ignored.
//
{'fraction_non_alphanumeric': 0.10101010101010101, 'fraction_numerical': 0.0008417508417508417, 'mean_word_length': 3.6598039215686273, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2836731', 'n_tokens_mistral': 1521, 'n_tokens_neox': 1438, 'n_words': 506}