//-----------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.
// 
//-----------------------------------------------------------------------
#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK
namespace Microsoft.Isam.Esent.Interop.Vista
{
    using System;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using Microsoft.Isam.Esent.Interop.Vista;
    /// 
    /// Used by  to return information about a record's usage
    /// requirements in user data space, number of set columns, number of
    /// values, and ESENT record structure overhead space.
    /// 
    [StructLayout(LayoutKind.Auto)]
    [SuppressMessage(
        "Microsoft.StyleCop.CSharp.NamingRules",
        "SA1300:ElementMustBeginWithUpperCaseLetter",
        Justification = "This should match the unmanaged API, which isn't capitalized.")]
    [Serializable]
    public struct JET_RECSIZE : IEquatable
    {
        /// 
        /// User data in the record.
        /// 
        private long userData;
        /// 
        /// User data associated with the record, but in the LV tree.
        /// 
        private long userLongValueData;
        /// 
        /// Record overhead, including key size.
        /// 
        private long overhead;
        /// 
        /// Overhead of storing the long-value data.
        /// 
        private long longValueOverhead;
        /// 
        /// Number of fixed and variable columns.
        /// 
        private long numNonTaggedColumns;
        /// 
        /// Number of tagged columns in the record.
        /// 
        private long numTaggedColumns;
        /// 
        /// Number of extrinsic (separated) long values.
        /// 
        private long numLongValues;
        /// 
        /// Number of multi-values (itag > 1) in the record.
        /// 
        private long numMultiValues;
        /// 
        /// Number of compressed columns in the record.
        /// 
        private long numCompressedColumns;
        /// 
        /// Size of user data after being compressed.
        /// 
        private long userDataAfterCompression;
        /// 
        /// Size of the long value data after compression.
        /// 
        private long userLongValueDataCompressed;
        /// 
        /// Gets the user data set in the record.
        /// 
        public long cbData
        {
            [DebuggerStepThrough]
            get { return this.userData; }
            internal set { this.userData = value; }
        }
        /// 
        /// Gets the user data set in the record, but stored in the long-value tree.
        /// 
        public long cbLongValueData
        {
            [DebuggerStepThrough]
            get { return this.userLongValueData; }
            internal set { this.userLongValueData = value; }
        }
        /// 
        /// Gets the overhead of the ESENT record structure for this record.
        /// This includes the record's key size.
        /// 
        public long cbOverhead
        {
            [DebuggerStepThrough]
            get { return this.overhead; }
            internal set { this.overhead = value; }
        }
        /// 
        /// Gets the overhead of the long-value data.
        /// 
        public long cbLongValueOverhead
        {
            [DebuggerStepThrough]
            get { return this.longValueOverhead; }
            internal set { this.longValueOverhead = value; }
        }
        /// 
        /// Gets the total number of fixed and variable columns set in this record.
        /// 
        public long cNonTaggedColumns
        {
            [DebuggerStepThrough]
            get { return this.numNonTaggedColumns; }
            internal set { this.numNonTaggedColumns = value; }
        }
        /// 
        /// Gets the total number of tagged columns set in this record.
        /// 
        public long cTaggedColumns
        {
            [DebuggerStepThrough]
            get { return this.numTaggedColumns; }
            internal set { this.numTaggedColumns = value; }
        }
        /// 
        /// Gets the total number of long values stored in the long-value tree
        /// for this record. This does not include intrinsic long values.
        /// 
        public long cLongValues
        {
            [DebuggerStepThrough]
            get { return this.numLongValues; }
            internal set { this.numLongValues = value; }
        }
        /// 
        /// Gets the accumulation of the total number of values beyond the first
        /// for all columns in the record.
        /// 
        public long cMultiValues
        {
            [DebuggerStepThrough]
            get { return this.numMultiValues; }
            internal set { this.numMultiValues = value; }
        }
        /// 
        /// Gets the total number of columns in the record which are compressed.
        /// 
        public long cCompressedColumns
        {
            [DebuggerStepThrough]
            get { return this.numCompressedColumns; }
            internal set { this.numCompressedColumns = value; }
        }
        /// 
        /// Gets the compressed size of user data in record. This is the same
        /// as  if no intrinsic long-values are compressed).
        /// 
        public long cbDataCompressed
        {
            [DebuggerStepThrough]
            get { return this.userDataAfterCompression; }
            internal set { this.userDataAfterCompression = value; }
        }
        /// 
        /// Gets the compressed size of user data in the long-value tree. This is
        /// the same as  if no separated long values
        /// are compressed.
        /// 
        public long cbLongValueDataCompressed
        {
            [DebuggerStepThrough]
            get { return this.userLongValueDataCompressed; }
            internal set { this.userLongValueDataCompressed = value; }
        }
        /// 
        /// Add the sizes in two JET_RECSIZE structures.
        /// 
        /// The first JET_RECSIZE.
        /// The second JET_RECSIZE.
        /// A JET_RECSIZE containing the result of adding the sizes in s1 and s2.
        public static JET_RECSIZE Add(JET_RECSIZE s1, JET_RECSIZE s2)
        {
            checked
            {
                return new JET_RECSIZE
                {
                    cbData = s1.cbData + s2.cbData,
                    cbDataCompressed = s1.cbDataCompressed + s2.cbDataCompressed,
                    cbLongValueData = s1.cbLongValueData + s2.cbLongValueData,
                    cbLongValueDataCompressed = s1.cbLongValueDataCompressed + s2.cbLongValueDataCompressed,
                    cbLongValueOverhead = s1.cbLongValueOverhead + s2.cbLongValueOverhead,
                    cbOverhead = s1.cbOverhead + s2.cbOverhead,
                    cCompressedColumns = s1.cCompressedColumns + s2.cCompressedColumns,
                    cLongValues = s1.cLongValues + s2.cLongValues,
                    cMultiValues = s1.cMultiValues + s2.cMultiValues,
                    cNonTaggedColumns = s1.cNonTaggedColumns + s2.cNonTaggedColumns,
                    cTaggedColumns = s1.cTaggedColumns + s2.cTaggedColumns,                    
                };
            }
        }
        /// 
        /// Add the sizes in two JET_RECSIZE structures.
        /// 
        /// The first JET_RECSIZE.
        /// The second JET_RECSIZE.
        /// A JET_RECSIZE containing the result of adding the sizes in left and right.
        public static JET_RECSIZE operator +(JET_RECSIZE left, JET_RECSIZE right)
        {
            return JET_RECSIZE.Add(left, right);
        }
        /// 
        /// Calculate the difference in sizes between two JET_RECSIZE structures.
        /// 
        /// The first JET_RECSIZE.
        /// The second JET_RECSIZE.
        /// A JET_RECSIZE containing the difference in sizes between s1 and s2.
        public static JET_RECSIZE Subtract(JET_RECSIZE s1, JET_RECSIZE s2)
        {
            checked
            {
                return new JET_RECSIZE
                {
                    cbData = s1.cbData - s2.cbData,
                    cbDataCompressed = s1.cbDataCompressed - s2.cbDataCompressed,
                    cbLongValueData = s1.cbLongValueData - s2.cbLongValueData,
                    cbLongValueDataCompressed = s1.cbLongValueDataCompressed - s2.cbLongValueDataCompressed,
                    cbLongValueOverhead = s1.cbLongValueOverhead - s2.cbLongValueOverhead,
                    cbOverhead = s1.cbOverhead - s2.cbOverhead,
                    cCompressedColumns = s1.cCompressedColumns - s2.cCompressedColumns,
                    cLongValues = s1.cLongValues - s2.cLongValues,
                    cMultiValues = s1.cMultiValues - s2.cMultiValues,
                    cNonTaggedColumns = s1.cNonTaggedColumns - s2.cNonTaggedColumns,
                    cTaggedColumns = s1.cTaggedColumns - s2.cTaggedColumns,
                };
            }
        }
        /// 
        /// Calculate the difference in sizes between two JET_RECSIZE structures.
        /// 
        /// The first JET_RECSIZE.
        /// The second JET_RECSIZE.
        /// A JET_RECSIZE containing the difference in sizes between left and right.
        public static JET_RECSIZE operator -(JET_RECSIZE left, JET_RECSIZE right)
        {
            return JET_RECSIZE.Subtract(left, right);
        }
        /// 
        /// Determines whether two specified instances of JET_RECSIZE
        /// are equal.
        /// 
        /// The first instance to compare.
        /// The second instance to compare.
        /// True if the two instances are equal.
        public static bool operator ==(JET_RECSIZE lhs, JET_RECSIZE rhs)
        {
            return lhs.Equals(rhs);
        }
        /// 
        /// Determines whether two specified instances of JET_RECSIZE
        /// are not equal.
        /// 
        /// The first instance to compare.
        /// The second instance to compare.
        /// True if the two instances are not equal.
        public static bool operator !=(JET_RECSIZE lhs, JET_RECSIZE rhs)
        {
            return !(lhs == rhs);
        }
        /// 
        /// Returns a value indicating whether this instance is equal
        /// to another instance.
        /// 
        /// An object to compare with this instance.
        /// True if the two instances are equal.
        public override bool Equals(object obj)
        {
            if (obj == null || this.GetType() != obj.GetType())
            {
                return false;
            }
            return this.Equals((JET_RECSIZE)obj);
        }
        /// 
        /// Returns the hash code for this instance.
        /// 
        /// The hash code for this instance.
        public override int GetHashCode()
        {
            // Put the data count members first so they aren't
            // shifted as much. Column counts cannot get as high
            // so we don't worry about losing fidelity.
            long hash = this.cbData
                        ^ this.cbDataCompressed << 1
                        ^ this.cbLongValueData << 2
                        ^ this.cbDataCompressed << 3
                        ^ this.cbLongValueDataCompressed << 4
                        ^ this.cbOverhead << 5
                        ^ this.cbLongValueOverhead << 6
                        ^ this.cNonTaggedColumns << 7
                        ^ this.cTaggedColumns << 8
                        ^ this.cLongValues << 9
                        ^ this.cMultiValues << 10
                        ^ this.cCompressedColumns << 11;
            return (int)(hash & 0xFFFFFFFF) ^ (int)(hash >> 32);
        }
        /// 
        /// Returns a value indicating whether this instance is equal
        /// to another instance.
        /// 
        /// An object to compare with this instance.
        /// True if the two instances are equal.
        public bool Equals(JET_RECSIZE other)
        {
            return this.cbData == other.cbData
                   && this.cbLongValueData == other.cbLongValueData
                   && this.cbOverhead == other.cbOverhead
                   && this.cbLongValueOverhead == other.cbLongValueOverhead
                   && this.cNonTaggedColumns == other.cNonTaggedColumns
                   && this.cTaggedColumns == other.cTaggedColumns
                   && this.cLongValues == other.cLongValues
                   && this.cMultiValues == other.cMultiValues
                   && this.cCompressedColumns == other.cCompressedColumns
                   && this.cbDataCompressed == other.cbDataCompressed
                   && this.cbLongValueDataCompressed == other.cbLongValueDataCompressed;
        }
        /// 
        /// Sets the fields of the object from a NATIVE_RECSIZE struct.
        /// 
        /// 
        /// The native recsize to set the values from.
        /// 
        internal void SetFromNativeRecsize(NATIVE_RECSIZE value)
        {
            // This is used on versions of ESENT that don't support JetGetRecordSize2.
            // That means compression isn't supported so we can default the compression
            // members to 'non compressed' values.
            checked
            {
                this.cbData = (long)value.cbData;
                this.cbDataCompressed = (long)value.cbData;
                this.cbLongValueData = (long)value.cbLongValueData;
                this.cbLongValueDataCompressed = (long)value.cbLongValueData;
                this.cbLongValueOverhead = (long)value.cbLongValueOverhead;
                this.cbOverhead = (long)value.cbOverhead;
                this.cCompressedColumns = 0;
                this.cLongValues = (long)value.cLongValues;
                this.cMultiValues = (long)value.cMultiValues;
                this.cNonTaggedColumns = (long)value.cNonTaggedColumns;
                this.cTaggedColumns = (long)value.cTaggedColumns;
            }
        }
        /// 
        /// Sets the fields of the object from a NATIVE_RECSIZE2 struct.
        /// 
        /// 
        /// The native recsize to set the values from.
        /// 
        internal void SetFromNativeRecsize(NATIVE_RECSIZE2 value)
        {
            checked
            {
                this.cbData = (long)value.cbData;
                this.cbDataCompressed = (long)value.cbDataCompressed;
                this.cbLongValueData = (long)value.cbLongValueData;
                this.cbLongValueDataCompressed = (long)value.cbLongValueDataCompressed;
                this.cbLongValueOverhead = (long)value.cbLongValueOverhead;
                this.cbOverhead = (long)value.cbOverhead;
                this.cCompressedColumns = (long)value.cCompressedColumns;
                this.cLongValues = (long)value.cLongValues;
                this.cMultiValues = (long)value.cMultiValues;
                this.cNonTaggedColumns = (long)value.cNonTaggedColumns;
                this.cTaggedColumns = (long)value.cTaggedColumns;
            }
        }
        /// 
        /// Gets a NATIVE_RECSIZE containing the values in this object.
        /// 
        /// 
        /// A NATIVE_RECSIZE initialized with the values in the object.
        /// 
        internal NATIVE_RECSIZE GetNativeRecsize()
        {
            unchecked
            {
                return new NATIVE_RECSIZE
                {
                    cbData = (ulong)this.cbData,
                    cbLongValueData = (ulong)this.cbLongValueData,
                    cbLongValueOverhead = (ulong)this.cbLongValueOverhead,
                    cbOverhead = (ulong)this.cbOverhead,
                    cLongValues = (ulong)this.cLongValues,
                    cMultiValues = (ulong)this.cMultiValues,
                    cNonTaggedColumns = (ulong)this.cNonTaggedColumns,
                    cTaggedColumns = (ulong)this.cTaggedColumns,
                };
            }
        }
        /// 
        /// Gets a NATIVE_RECSIZE2 containing the values in this object.
        /// 
        /// 
        /// A NATIVE_RECSIZE2 initialized with the values in the object.
        /// 
        internal NATIVE_RECSIZE2 GetNativeRecsize2()
        {
            unchecked
            {
                return new NATIVE_RECSIZE2
                {
                    cbData = (ulong)this.cbData,
                    cbDataCompressed = (ulong)this.cbDataCompressed,
                    cbLongValueData = (ulong)this.cbLongValueData,
                    cbLongValueDataCompressed = (ulong)this.cbLongValueDataCompressed,
                    cbLongValueOverhead = (ulong)this.cbLongValueOverhead,
                    cbOverhead = (ulong)this.cbOverhead,
                    cCompressedColumns = (ulong)this.cCompressedColumns,
                    cLongValues = (ulong)this.cLongValues,
                    cMultiValues = (ulong)this.cMultiValues,
                    cNonTaggedColumns = (ulong)this.cNonTaggedColumns,
                    cTaggedColumns = (ulong)this.cTaggedColumns,
                };
            }
        }
    }
    /// 
    /// The native version of the JET_RECSIZE structure.
    /// 
    [StructLayout(LayoutKind.Sequential)]
    [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules",
        "SA1305:FieldNamesMustNotUseHungarianNotation",
        Justification = "This should match the unmanaged API, which isn't capitalized.")]
    [SuppressMessage(
        "Microsoft.StyleCop.CSharp.NamingRules",
        "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter",
        Justification = "This should match the unmanaged API, which isn't capitalized.")]
    internal struct NATIVE_RECSIZE
    {
        /// 
        /// User data in record.
        /// 
        public ulong cbData;
        /// 
        /// User data associated with the record but stored in the long-value
        /// tree. Does NOT count intrinsic long-values.
        /// 
        public ulong cbLongValueData;
        /// 
        /// Record overhead.
        /// 
        public ulong cbOverhead;
        /// 
        /// Overhead of long-value data. Does not count intrinsic long-values.
        /// 
        public ulong cbLongValueOverhead;
        /// 
        /// Total number of fixed/variable columns.
        /// 
        public ulong cNonTaggedColumns;
        /// 
        /// Total number of tagged columns.
        /// 
        public ulong cTaggedColumns;
        /// 
        /// Total number of values stored in the long-value tree for this record.
        /// Does NOT count intrinsic long-values.
        /// 
        public ulong cLongValues;
        /// 
        /// Total number of values beyond the first for each column in the record.
        /// 
        public ulong cMultiValues;
    }
    /// 
    /// The native version of the JET_RECSIZE2 structure.
    /// 
    [StructLayout(LayoutKind.Sequential)]
    [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules",
        "SA1305:FieldNamesMustNotUseHungarianNotation",
        Justification = "This should match the unmanaged API, which isn't capitalized.")]
    [SuppressMessage(
        "Microsoft.StyleCop.CSharp.NamingRules",
        "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter",
        Justification = "This should match the unmanaged API, which isn't capitalized.")]
    internal struct NATIVE_RECSIZE2
    {
        /// 
        /// User data in record.
        /// 
        public ulong cbData;
        /// 
        /// User data associated with the record but stored in the long-value
        /// tree. Does NOT count intrinsic long-values.
        /// 
        public ulong cbLongValueData;
        /// 
        /// Record overhead.
        /// 
        public ulong cbOverhead;
        /// 
        /// Overhead of long-value data. Does not count intrinsic long-values.
        /// 
        public ulong cbLongValueOverhead;
        /// 
        /// Total number of fixed/variable columns.
        /// 
        public ulong cNonTaggedColumns;
        /// 
        /// Total number of tagged columns.
        /// 
        public ulong cTaggedColumns;
        /// 
        /// Total number of values stored in the long-value tree for this record.
        /// Does NOT count intrinsic long-values.
        /// 
        public ulong cLongValues;
        /// 
        /// Total number of values beyond the first for each column in the record.
        /// 
        public ulong cMultiValues;
        /// 
        /// Total number of columns which are compressed.
        /// 
        public ulong cCompressedColumns;
        /// 
        /// Compressed size of user data in record. Same as cbData if no intrinsic
        /// long-values are compressed.
        /// 
        public ulong cbDataCompressed;
        /// 
        /// Compressed size of user data in the long-value tree. Same as
        /// cbLongValue data if no separated long values are compressed.
        /// 
        public ulong cbLongValueDataCompressed;
    }
}
#endif // !MANAGEDESENT_ON_WSA