# (c) 2021 Ashok P. Nadkarni
# See LICENSE for license terms.

oo::class create ${NS}::Struct {
    constructor {definition args} {
        # Constructs a script level object that maps to a C struct definition.
        #  definition - defines the layout and type of the C struct fields
        #  args - options. Currently the only option is `-clear`
        # The created object can be used to pass arguments to and from
        # functions, allocate memory, encode and decode native C structs
        # in memory etc.
        #
        # The $definition argument is a dictionary mapping field names to the
        # corresponding types. See [Structs][::Concepts::Structs] for more
        # information.
        #
        # The name of the created struct is the same as the name of the
        # returned object without the initial `::` global namespace qualifier.
        # This name can be retrieved with the [name] method and is used to
        # identify the struct when tagging pointers and for typing function
        # parameters and nested struct fields.
        #
        # If the `-clear` option is present, the memory of structures of this
        # type is cleared before the field values are initialized. In this case,
        # missing field values in a struct value will not result in an error
        # being raised even if no default annotation is included for the field.
        # This also effectively provides a default zero value for all fields.
        #
    }
    method allocate {{count 1}} {
        # Allocates memory for one or more C structs.
        #   count - number of structs to allocate
        #
        # The allocated memory is not initialized even if the struct definition
        # includes the `-clear` option.
        #
        # It must be freed by calling the [free] method.
        #
        # Returns a safe pointer to the allocated memory tagged with the
        # struct name.
    }
    method new {{initval {}}} {
        # Allocates and initializes a native struct in memory.
        #  initval - initial value for the struct as a dictionary mapping field
        #    names to values.
        #
        # If no argument is supplied or fields are missing, defaults from the
        # struct definition are used for initialization. An error is raised
        # if any fields are not defaulted.
        #
        # The allocated memory must be freed by calling the [free] method for the
        # struct.
        #
        # Returns a safe pointer to the allocated memory tagged with the
        # struct name.
    }
    method getnativefields {pointer fieldnames {index 0}} {
        # Retrieve values of multiple fields from a native struct in memory.
        #  pointer - pointer to memory allocated for the C struct or array. Must be
        #    a safe pointer tagged with the struct name.
        #  fieldnames - list of field names
        #  index - If present, $pointer is interpreted as pointing to an array of
        #    structs and this is the index into that array.
        #
        # Returns a list of field values in the same order as $fieldnames
    }
    method fromnative {pointer {index 0}} {
        # Decodes native C struct(s) in memory into a Tcl dictionary.
        #  pointer - safe pointer to the C struct or array of structs in memory
        #  index - the index position at which the struct is to be written.
        #    Note this interpreted as an **index** into an array of structs, not as
        #    a byte offset into memory.
        #
        # The decoded dictionary or dictionaries are keyed by the field
        # names of the struct.
        #
        # See also: fromnative! tonative, frombinary
        #
        # Returns a dictionary of the decoded struct.
    }
    method fromnative! {pointer {index 0}} {
        # Decodes native C struct(s) in memory into a Tcl dictionary.
        #  pointer - unsafe pointer to the C struct or array of structs in memory
        #  index - the index position at which the struct is to be written.
        #    Note this interpreted as an **index** into an array of structs, not as
        #    a byte offset into memory.
        #
        # The decoded dictionary or dictionaries are keyed by the field
        # names of the struct.
        #
        # See also: fromnative, tonative, frombinary
        #
        # Returns a dictionary of the decoded struct.
    }
    method tonative {pointer initializer {index 0}} {
        # Writes the Tcl dictionary representation of a C struct value to memory
        # in native form.
        #  pointer - pointer to memory allocated for the C struct or array. Must be
        #    tagged with the struct name.
        #  initializer - the Tcl dictionary value
        #  index - the index position at which the struct is to be written.
        #    Note this interpreted as an **index** into an array of structs, not as
        #    a byte offset into memory.
        #
        # See also: fromnative tobinary
        #
    }
    method getnative {pointer fieldname {index 0}} {
        # Returns the value of a field in a native structure in memory
        #  pointer - pointer to memory allocated for the C struct or array. Must be
        #    a safe pointer tagged with the struct name.
        #  fieldname - name of the field
        #  index - If present, $pointer is interpreted as pointing to an array of
        #    structs and this is the index into that array.
        #
        # In the case of fields of type pointer, the returned pointer is registered
        # as a safe pointer unless the field was marked with the `unsafe` annotation.
    }
    method setnative {pointer fieldname value {index 0}} {
        # Sets the value of a field in a native structure in memory
        #  pointer - pointer to memory allocated for the C struct or array. Must be
        #    a safe pointer tagged with the struct name.
        #  fieldname - name of the field
        #  value - value to store in the field
        #  index - If present, $pointer is interpreted as pointing to an array of
        #    structs and this is the index into that array.
        #
    }
    method fieldpointer {pointer fieldname {tag ""} {index 0}} {
        # Returns a pointer corresponding to the address of a field within a
        # native structure
        #  pointer - pointer to memory allocated for the C struct or array. Must be
        #    a safe pointer tagged with the struct name.
        #  fieldname - name of the field
        #  tag - tag for the returned pointer
        #  index - If present, $pointer is interpreted as pointing to an array of
        #    structs and this is the index into that array.
        #
        # Note the returned pointer is not registered as a safe pointer.
        #
    }
    method free {pointer} {
        # Frees memory that was allocated for a native C struct.
        #  pointer - a pointer returned by [allocate]
    }
    method info {} {
        # Returns a dictionary containing information about the struct layout
        #
        # The returned dictionary has the following fields:
        # Size - size of the struct
        # Alignment - struct alignment
        # Fields - dictionary of fields keyed by field name. The value is another
        #   nested dictionary with keys *Size*, *Offset*, and *Definition*
        #   containing the size, offset in struct, and type definition of the field.
    }
    method describe {} {
        # Returns a human-readable description of the C struct definition.
        #
        # This is primarily for debugging and troubleshooting purposes.
    }
    method frombinary {bin_value} {
        # Decodes a Tcl binary string containing a native C struct into
        # a Tcl dictionary.
        #  bin_value - a Tcl binary value containing the C struct
        # Returns the dictionary representation.
    }
    method tobinary {dict_value} {
        # Encodes the Tcl representation of a C struct value into a
        # Tcl binary string.
        #  dict_value - a Tcl dictionary representation of a C struct value.
        # Returns the binary string containing the native C struct.
    }
    method name {} {
        # Returns the name of the struct.
        #
        # Note the name of the struct is different from the name of
        # the object name.
    }
}
