#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using Google.Protobuf.Descriptors;

namespace Google.Protobuf
{
    /// <summary>
    /// This class is used internally by the Protocol Buffer Library and generated
    /// message implementations. It is public only for the sake of those generated
    /// messages. Others should not use this class directly.
    /// <para>
    /// This class contains constants and helper functions useful for dealing with
    /// the Protocol Buffer wire format.
    /// </para>
    /// </summary>
    public static class WireFormat
    {
        #region Fixed sizes.

        // TODO(jonskeet): Move these somewhere else. They're messy. Consider making FieldType a smarter kind of enum
        internal const int Fixed32Size = 4;
        internal const int Fixed64Size = 8;
        internal const int SFixed32Size = 4;
        internal const int SFixed64Size = 8;
        internal const int FloatSize = 4;
        internal const int DoubleSize = 8;
        internal const int BoolSize = 1;

        #endregion

        public enum WireType : uint
        {
            Varint = 0,
            Fixed64 = 1,
            LengthDelimited = 2,
            StartGroup = 3,
            EndGroup = 4,
            Fixed32 = 5
        }
        
        private const int TagTypeBits = 3;
        private const uint TagTypeMask = (1 << TagTypeBits) - 1;

        /// <summary>
        /// Given a tag value, determines the wire type (lower 3 bits).
        /// </summary>
        public static WireType GetTagWireType(uint tag)
        {
            return (WireType) (tag & TagTypeMask);
        }

        public static bool IsEndGroupTag(uint tag)
        {
            return (WireType) (tag & TagTypeMask) == WireType.EndGroup;
        }

        /// <summary>
        /// Given a tag value, determines the field number (the upper 29 bits).
        /// </summary>
        public static int GetTagFieldNumber(uint tag)
        {
            return (int) tag >> TagTypeBits;
        }

        /// <summary>
        /// Makes a tag value given a field number and wire type.
        /// </summary>
        public static uint MakeTag(int fieldNumber, WireType wireType)
        {
            return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
        }

        public static uint MakeTag(FieldDescriptor field)
        {
            return MakeTag(field.FieldNumber, GetWireType(field));
        }

        /// <summary>
        /// Returns the wire type for the given field descriptor. This differs
        /// from GetWireType(FieldType) for packed repeated fields.
        /// </summary>
        internal static WireType GetWireType(FieldDescriptor descriptor)
        {
            return descriptor.IsPacked ? WireType.LengthDelimited : GetWireType(descriptor.FieldType);
        }

        /// <summary>
        /// Converts a field type to its wire type. Done with a switch for the sake
        /// of speed - this is significantly faster than a dictionary lookup.
        /// </summary>
        public static WireType GetWireType(FieldType fieldType)
        {
            switch (fieldType)
            {
                case FieldType.Double:
                    return WireType.Fixed64;
                case FieldType.Float:
                    return WireType.Fixed32;
                case FieldType.Int64:
                case FieldType.UInt64:
                case FieldType.Int32:
                    return WireType.Varint;
                case FieldType.Fixed64:
                    return WireType.Fixed64;
                case FieldType.Fixed32:
                    return WireType.Fixed32;
                case FieldType.Bool:
                    return WireType.Varint;
                case FieldType.String:
                    return WireType.LengthDelimited;
                case FieldType.Group:
                    return WireType.StartGroup;
                case FieldType.Message:
                case FieldType.Bytes:
                    return WireType.LengthDelimited;
                case FieldType.UInt32:
                    return WireType.Varint;
                case FieldType.SFixed32:
                    return WireType.Fixed32;
                case FieldType.SFixed64:
                    return WireType.Fixed64;
                case FieldType.SInt32:
                case FieldType.SInt64:
                case FieldType.Enum:
                    return WireType.Varint;
                default:
                    throw new ArgumentOutOfRangeException("fieldType", "No such field type");
            }
        }
    }
}