// 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.

package com.google.protobuf;

/**
 * RawMessageInfo stores the same amount of information as {@link MessageInfo} but in a more compact
 * format.
 */
final class RawMessageInfo implements MessageInfo {

  private final MessageLite defaultInstance;

  /**
   * The compact format packs everything in a String object and a Object[] array. The String object
   * is encoded with field number, field type, hasbits offset, oneof index, etc., whereas the
   * Object[] array contains field references, class references, instance references, etc.
   *
   * <p>The String object encodes a sequence of integers into UTF-16 characters. For each int, it
   * will be encoding into 1 to 3 UTF-16 characters depending on its unsigned value:
   *
   * <ul>
   *   <li>1 char: [c1: 0x0000 - 0xD7FF] = int of the same value.
   *   <li>2 chars: [c1: 0xE000 - 0xFFFF], [c2: 0x0000 - 0xD7FF] = (c2 << 13) | (c1 & 0x1FFF)
   *   <li>3 chars: [c1: 0xE000 - 0xFFFF], [c2: 0xE000 - 0xFFFF], [c3: 0x0000 - 0xD7FF] = (c3 << 26)
   *       | ((c2 & 0x1FFF) << 13) | (c1 & 0x1FFF)
   * </ul>
   *
   * <p>Note that we don't use UTF-16 surrogate pairs [0xD800 - 0xDFFF] because they have to come in
   * pairs to form a valid UTF-16char sequence and don't help us encode values more efficiently.
   *
   * <p>The integer sequence encoded in the String object has the following layout:
   *
   * <ul>
   *   <li>[0]: flags, flags & 0x1 = is proto2?, flags & 0x2 = is message?.
   *   <li>[1]: field count, if 0, this is the end of the integer sequence and the corresponding
   *       Object[] array should be null.
   *   <li>[2]: oneof count
   *   <li>[3]: hasbits count, how many hasbits integers are generated.
   *   <li>[4]: min field number
   *   <li>[5]: max field number
   *   <li>[6]: total number of entries need to allocate
   *   <li>[7]: map field count
   *   <li>[8]: repeated field count, this doesn't include map fields.
   *   <li>[9]: size of checkInitialized array
   *   <li>[...]: field entries
   * </ul>
   *
   * <p>Each field entry starts with a field number and the field type:
   *
   * <ul>
   *   <li>[0]: field number
   *   <li>[1]: field type with extra bits:
   *       <ul>
   *         <li>v & 0xFF = field type as defined in the FieldType class
   *         <li>v & 0x100 = is required?
   *         <li>v & 0x200 = is checkUtf8?
   *         <li>v & 0x400 = needs isInitialized check?
   *         <li>v & 0x800 = is map field with proto2 enum value?
   *       </ul>
   * </ul>
   *
   * If the file is proto2 and this is a singular field:
   *
   * <ul>
   *   <li>[2]: hasbits offset
   * </ul>
   *
   * If the field is in an oneof:
   *
   * <ul>
   *   <li>[2]: oenof index
   * </ul>
   *
   * For other types, the field entry only has field number and field type.
   *
   * <p>The Object[] array has 3 sections:
   *
   * <ul>
   *   <li>---- oneof section ----
   *       <ul>
   *         <li>[0]: value field for oneof 1.
   *         <li>[1]: case field for oneof 1.
   *         <li>...
   *         <li>[.]: value field for oneof n.
   *         <li>[.]: case field for oneof n.
   *       </ul>
   *   <li>---- hasbits section ----
   *       <ul>
   *         <li>[.]: hasbits field 1
   *         <li>[.]: hasbits field 2
   *         <li>...
   *         <li>[.]: hasbits field n
   *       </ul>
   *   <li>---- field section ----
   *       <ul>
   *         <li>[...]: field entries
   *       </ul>
   * </ul>
   *
   * <p>In the Object[] array, field entries are ordered in the same way as field entries in the
   * String object. The size of each entry is determined by the field type.
   *
   * <ul>
   *   <li>Oneof field:
   *       <ul>
   *         <li>Oneof message field:
   *             <ul>
   *               <li>[0]: message class reference.
   *             </ul>
   *         <li>Oneof enum fieldin proto2:
   *             <ul>
   *               <li>[0]: EnumLiteMap
   *             </ul>
   *         <li>For all other oneof fields, field entry in the Object[] array is empty.
   *       </ul>
   *   <li>Repeated message field:
   *       <ul>
   *         <li>[0]: field reference
   *         <li>[1]: message class reference
   *       </ul>
   *   <li>Proto2 singular/repeated enum field:
   *       <ul>
   *         <li>[0]: field reference
   *         <li>[1]: EnumLiteMap
   *       </ul>
   *   <li>Map field with a proto2 enum value:
   *       <ul>
   *         <li>[0]: field reference
   *         <li>[1]: map default entry instance
   *         <li>[2]: EnumLiteMap
   *       </ul>
   *   <li>Map field with other value types:
   *       <ul>
   *         <li>[0]: field reference
   *         <li>[1]: map default entry instance
   *       </ul>
   *   <li>All other field type:
   *       <ul>
   *         <li>[0]: field reference
   *       </ul>
   * </ul>
   *
   * <p>In order to read the field info from this compact format, a reader needs to progress through
   * the String object and the Object[] array simultaneously.
   */
  private final String info;

  private final Object[] objects;
  private final int flags;

  RawMessageInfo(MessageLite defaultInstance, String info, Object[] objects) {
    this.defaultInstance = defaultInstance;
    this.info = info;
    this.objects = objects;
    int position = 0;
    int value = (int) info.charAt(position++);
    if (value < 0xD800) {
      flags = value;
    } else {
      int result = value & 0x1FFF;
      int shift = 13;
      while ((value = info.charAt(position++)) >= 0xD800) {
        result |= (value & 0x1FFF) << shift;
        shift += 13;
      }
      flags = result | (value << shift);
    }
  }

  String getStringInfo() {
    return info;
  }

  Object[] getObjects() {
    return objects;
  }

  @Override
  public MessageLite getDefaultInstance() {
    return defaultInstance;
  }

  @Override
  public ProtoSyntax getSyntax() {
    return (flags & 0x1) == 0x1 ? ProtoSyntax.PROTO2 : ProtoSyntax.PROTO3;
  }

  @Override
  public boolean isMessageSetWireFormat() {
    return (flags & 0x2) == 0x2;
  }
}
