Implementation work for Lite runtime and generator
diff --git a/src/ProtocolBuffers/FieldSet.cs b/src/ProtocolBuffers/FieldSet.cs
index 7c373b9..3ac3e3d 100644
--- a/src/ProtocolBuffers/FieldSet.cs
+++ b/src/ProtocolBuffers/FieldSet.cs
@@ -39,6 +39,20 @@
 using Google.ProtocolBuffers.Descriptors;
 
 namespace Google.ProtocolBuffers {
+
+  public interface IFieldDescriptorLite : IComparable<IFieldDescriptorLite> {
+    bool IsRepeated { get; }
+    bool IsRequired { get; }
+    bool IsPacked { get; }
+    bool IsExtension { get; }
+    bool MessageSetWireFormat { get; } //field.ContainingType.Options.MessageSetWireFormat
+    int FieldNumber { get; }
+    IEnumLiteMap EnumType { get; }
+    FieldType FieldType { get; }
+    MappedType MappedType { get; }
+    object DefaultValue { get; }
+  }
+
   /// <summary>
   /// A class which represents an arbitrary set of fields of some message type.
   /// This is used to implement DynamicMessage, and also to represent extensions
@@ -56,17 +70,17 @@
   /// </summary>
   internal sealed class FieldSet {
 
-    private static readonly FieldSet defaultInstance = new FieldSet(new Dictionary<FieldDescriptor, object>()).MakeImmutable();
+    private static readonly FieldSet defaultInstance = new FieldSet(new Dictionary<IFieldDescriptorLite, object>()).MakeImmutable();
 
-    private IDictionary<FieldDescriptor, object> fields;
+    private IDictionary<IFieldDescriptorLite, object> fields;
 
-    private FieldSet(IDictionary<FieldDescriptor, object> fields) {
+    private FieldSet(IDictionary<IFieldDescriptorLite, object> fields) {
       this.fields = fields;
     }
 
     public static FieldSet CreateInstance() {
       // Use SortedList to keep fields in the canonical order
-      return new FieldSet(new SortedList<FieldDescriptor, object>());
+      return new FieldSet(new SortedList<IFieldDescriptorLite, object>());
     }
 
     /// <summary>
@@ -85,8 +99,8 @@
       }
 
       if (hasRepeats) {
-        var tmp = new SortedList<FieldDescriptor, object>();
-        foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
+        var tmp = new SortedList<IFieldDescriptorLite, object>();
+        foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
           IList<object> list = entry.Value as IList<object>;
           tmp[entry.Key] = list == null ? entry.Value : Lists.AsReadOnly(list);
         }
@@ -110,14 +124,26 @@
     /// is immutable, the entries may not be (i.e. any repeated values are represented by
     /// mutable lists). The behaviour is not specified if the contents are mutated.
     /// </summary>
-    internal IDictionary<FieldDescriptor, object> AllFields {
+    internal IDictionary<IFieldDescriptorLite, object> AllFields {
       get { return Dictionaries.AsReadOnly(fields); }
     }
-
+#if !LITE
     /// <summary>
-    /// See <see cref="IMessage.HasField"/>.
+    /// Force coercion to full descriptor dictionary.
     /// </summary>
-    public bool HasField(FieldDescriptor field) {
+    internal IDictionary<Descriptors.FieldDescriptor, object> AllFieldDescriptors {
+      get {
+        SortedList<Descriptors.FieldDescriptor, object> copy = new SortedList<Google.ProtocolBuffers.Descriptors.FieldDescriptor, object>();
+        foreach (KeyValuePair<IFieldDescriptorLite, object> fd in fields)
+          copy.Add((Descriptors.FieldDescriptor)fd.Key, fd.Value);
+        return Dictionaries.AsReadOnly(copy); 
+      }
+    }
+#endif
+    /// <summary>
+    /// See <see cref="IMessageLite.HasField"/>.
+    /// </summary>
+    public bool HasField(IFieldDescriptorLite field) {
       if (field.IsRepeated) {
         throw new ArgumentException("HasField() can only be called on non-repeated fields.");
       }
@@ -133,7 +159,7 @@
     }
 
     /// <summary>
-    /// See <see cref="IMessage.Item(FieldDescriptor)"/>
+    /// See <see cref="IMessageLite.Item(IFieldDescriptorLite)"/>
     /// </summary>
     /// <remarks>
     /// If the field is not set, the behaviour when fetching this property varies by field type:
@@ -153,7 +179,7 @@
     /// to ensure it is of an appropriate type.
     /// </remarks>
     /// 
-    internal object this[FieldDescriptor field] {
+    internal object this[IFieldDescriptorLite field] {
       get {
         object result;
         if (fields.TryGetValue(field, out result)) {
@@ -191,9 +217,9 @@
     }
 
     /// <summary>
-    /// See <see cref="IMessage.Item(FieldDescriptor,int)" />
+    /// See <see cref="IMessageLite.Item(IFieldDescriptorLite,int)" />
     /// </summary>
-    internal object this[FieldDescriptor field, int index] {
+    internal object this[IFieldDescriptorLite field, int index] {
       get {
         if (!field.IsRepeated) {
           throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields.");
@@ -217,7 +243,7 @@
     /// <summary>
     /// See <see cref="IBuilder{TMessage, TBuilder}.AddRepeatedField" />
     /// </summary>
-    internal void AddRepeatedField(FieldDescriptor field, object value) {
+    internal void AddRepeatedField(IFieldDescriptorLite field, object value) {
       if (!field.IsRepeated) {
         throw new ArgumentException("AddRepeatedField can only be called on repeated fields.");
       }
@@ -233,12 +259,12 @@
     /// <summary>
     /// Returns an enumerator for the field map. Used to write the fields out.
     /// </summary>
-    internal IEnumerator<KeyValuePair<FieldDescriptor, object>> GetEnumerator() {
+    internal IEnumerator<KeyValuePair<IFieldDescriptorLite, object>> GetEnumerator() {
       return fields.GetEnumerator();
     }
 
     /// <summary>
-    /// See <see cref="IMessage.IsInitialized" />
+    /// See <see cref="IMessageLite.IsInitialized" />
     /// </summary>
     /// <remarks>
     /// Since FieldSet itself does not have any way of knowing about
@@ -248,17 +274,17 @@
     /// </remarks>
     internal bool IsInitialized {
       get {
-        foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
-          FieldDescriptor field = entry.Key;
+        foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
+          IFieldDescriptorLite field = entry.Key;
           if (field.MappedType == MappedType.Message) {
             if (field.IsRepeated) {
-              foreach(IMessage message in (IEnumerable) entry.Value) {
+              foreach(IMessageLite message in (IEnumerable) entry.Value) {
                 if (!message.IsInitialized) {
                   return false;
                 }
               }
             } else {
-              if (!((IMessage) entry.Value).IsInitialized) {
+              if (!((IMessageLite)entry.Value).IsInitialized) {
                 return false;
               }
             }
@@ -273,8 +299,8 @@
     /// descriptor are present in this field set, as well as whether
     /// all the embedded messages are themselves initialized.
     /// </summary>
-    internal bool IsInitializedWithRespectTo(MessageDescriptor type) {
-      foreach (FieldDescriptor field in type.Fields) {
+    internal bool IsInitializedWithRespectTo(IEnumerable typeFields) {
+      foreach (IFieldDescriptorLite field in typeFields) {
         if (field.IsRequired && !HasField(field)) {
           return false;
         }
@@ -285,14 +311,14 @@
     /// <summary>
     /// See <see cref="IBuilder{TMessage, TBuilder}.ClearField" />
     /// </summary>
-    public void ClearField(FieldDescriptor field) {
+    public void ClearField(IFieldDescriptorLite field) {
       fields.Remove(field);
     }
 
     /// <summary>
-    /// See <see cref="IMessage.GetRepeatedFieldCount" />
+    /// See <see cref="IMessageLite.GetRepeatedFieldCount" />
     /// </summary>
-    public int GetRepeatedFieldCount(FieldDescriptor field) {
+    public int GetRepeatedFieldCount(IFieldDescriptorLite field) {
       if (!field.IsRepeated) {
         throw new ArgumentException("GetRepeatedFieldCount() can only be called on repeated fields.");
       }
@@ -300,64 +326,63 @@
       return ((IList<object>) this[field]).Count;
     }
 
+#if !LITE
+    /// <summary>
+    /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessageLite)" />
+    /// </summary>
+    public void MergeFrom(IMessage other) {
+      foreach (KeyValuePair<Descriptors.FieldDescriptor, object> fd in other.AllFields)
+        MergeField(fd.Key, fd.Value);
+    }
+#endif
+
     /// <summary>
     /// Implementation of both <c>MergeFrom</c> methods.
     /// </summary>
     /// <param name="otherFields"></param>
-    private void MergeFields(IEnumerable<KeyValuePair<FieldDescriptor, object>> otherFields) {
+    public void MergeFrom(FieldSet other) {
       // Note:  We don't attempt to verify that other's fields have valid
       //   types.  Doing so would be a losing battle.  We'd have to verify
       //   all sub-messages as well, and we'd have to make copies of all of
       //   them to insure that they don't change after verification (since
-      //   the IMessage interface itself cannot enforce immutability of
+      //   the IMessageLite interface itself cannot enforce immutability of
       //   implementations).
       // TODO(jonskeet):  Provide a function somewhere called MakeDeepCopy()
       //   which allows people to make secure deep copies of messages.
 
-      foreach (KeyValuePair<FieldDescriptor, object> entry in otherFields) {
-        FieldDescriptor field = entry.Key;
-        object existingValue;
-        fields.TryGetValue(field, out existingValue);
-        if (field.IsRepeated) {
-          if (existingValue == null) {
-            existingValue = new List<object>();
-            fields[field] = existingValue;
-          }
-          IList<object> list = (IList<object>) existingValue;
-          foreach (object otherValue in (IEnumerable) entry.Value) {
-            list.Add(otherValue);
-          }
-        } else if (field.MappedType == MappedType.Message && existingValue != null) {
-          IMessage existingMessage = (IMessage)existingValue;
-          IMessage merged = existingMessage.WeakToBuilder()
-              .WeakMergeFrom((IMessage) entry.Value)
-              .WeakBuild();
-          this[field] = merged;
-        } else {
-          this[field] = entry.Value;
+      foreach (KeyValuePair<IFieldDescriptorLite, object> entry in other.fields) {
+        MergeField(entry.Key, entry.Value);
+      }
+    }
+
+    private void MergeField(IFieldDescriptorLite field, object mergeValue) {
+      object existingValue;
+      fields.TryGetValue(field, out existingValue);
+      if (field.IsRepeated) {
+        if (existingValue == null) {
+          existingValue = new List<object>();
+          fields[field] = existingValue;
         }
+        IList<object> list = (IList<object>) existingValue;
+        foreach (object otherValue in (IEnumerable)mergeValue) {
+          list.Add(otherValue);
+        }
+      } else if (field.MappedType == MappedType.Message && existingValue != null) {
+        IMessageLite existingMessage = (IMessageLite)existingValue;
+        IMessageLite merged = existingMessage.WeakToBuilder()
+          .WeakMergeFrom((IMessageLite)mergeValue)
+          .WeakBuild();
+        this[field] = merged;
+      } else {
+        this[field] = mergeValue;
       }
     }
 
     /// <summary>
-    /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessage)" />
-    /// </summary>
-    public void MergeFrom(IMessage other) {
-      MergeFields(other.AllFields);
-    }
-
-    /// <summary>
-    /// Like <see cref="MergeFrom(IMessage)"/>, but merges from another <c>FieldSet</c>.
-    /// </summary>
-    public void MergeFrom(FieldSet other) {
-      MergeFields(other.fields);
-    }
-
-    /// <summary>
-    /// See <see cref="IMessage.WriteTo(CodedOutputStream)" />.
+    /// See <see cref="IMessageLite.WriteTo(CodedOutputStream)" />.
     /// </summary>
     public void WriteTo(CodedOutputStream output) {
-      foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
+      foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
         WriteField(entry.Key, entry.Value, output);
       }
     }
@@ -365,9 +390,9 @@
     /// <summary>
     /// Writes a single field to a CodedOutputStream.
     /// </summary>
-    public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) {
-      if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
-        output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value);
+    public void WriteField(IFieldDescriptorLite field, Object value, CodedOutputStream output) {
+      if (field.IsExtension && field.MessageSetWireFormat) {
+        output.WriteMessageSetExtension(field.FieldNumber, (IMessageLite) value);
       } else {
         if (field.IsRepeated) {
           IEnumerable valueList = (IEnumerable) value;
@@ -395,18 +420,18 @@
     }
 
     /// <summary>
-    /// See <see cref="IMessage.SerializedSize" />. It's up to the caller to
+    /// See <see cref="IMessageLite.SerializedSize" />. It's up to the caller to
     /// cache the resulting size if desired.
     /// </summary>
     public int SerializedSize {
       get {
         int size = 0;
-        foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
-          FieldDescriptor field = entry.Key;
+        foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
+          IFieldDescriptorLite field = entry.Key;
           object value = entry.Value;
 
-          if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
-            size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage)value);
+          if (field.IsExtension && field.MessageSetWireFormat) {
+            size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessageLite)value);
           } else {
             if (field.IsRepeated) {
               IEnumerable valueList = (IEnumerable)value;
@@ -440,7 +465,7 @@
     /// </remarks>
     /// <exception cref="ArgumentException">The value is not of the right type.</exception>
     /// <exception cref="ArgumentNullException">The value is null.</exception>
-    private static void VerifyType(FieldDescriptor field, object value) {
+    private static void VerifyType(IFieldDescriptorLite field, object value) {
       ThrowHelper.ThrowIfNull(value, "value");
       bool isValid = false;
       switch (field.MappedType) {
@@ -454,12 +479,15 @@
         case MappedType.String:      isValid = value is string; break;
         case MappedType.ByteString:  isValid = value is ByteString; break;        
         case MappedType.Enum:
-          EnumValueDescriptor enumValue = value as EnumValueDescriptor;
-          isValid = enumValue != null && enumValue.EnumDescriptor == field.EnumType;
+          IEnumLite enumValue = value as IEnumLite;
+          isValid = enumValue != null && field.EnumType.IsValidValue(enumValue);
           break;
         case MappedType.Message:
-          IMessage messageValue = value as IMessage;
-          isValid = messageValue != null && messageValue.DescriptorForType == field.MessageType;
+          IMessageLite messageValue = value as IMessageLite;
+          isValid = messageValue != null;
+#if !LITE
+          isValid = isValid && ((IMessage)messageValue).DescriptorForType == ((Google.ProtocolBuffers.Descriptors.FieldDescriptor)field).MessageType;
+#endif
           break;
       }
 
@@ -468,10 +496,16 @@
         // the stack trace which exact call failed, since the whole chain is
         // considered one line of code.  So, let's make sure to include the
         // field name and other useful info in the exception.
-        throw new ArgumentException("Wrong object type used with protocol message reflection. "
-            + "Message type \"" + field.ContainingType.FullName
-            + "\", field \"" + (field.IsExtension ? field.FullName : field.Name)
-            + "\", value was type \"" + value.GetType().Name + "\".");
+        string message = "Wrong object type used with protocol message reflection.";
+#if !LITE
+        Google.ProtocolBuffers.Descriptors.FieldDescriptor fieldinfo = field as Google.ProtocolBuffers.Descriptors.FieldDescriptor;
+        if (fieldinfo != null) {
+          message += "Message type \"" + fieldinfo.ContainingType.FullName;
+          message += "\", field \"" + (fieldinfo.IsExtension ? fieldinfo.FullName : fieldinfo.Name);
+          message += "\", value was type \"" + value.GetType().Name + "\".";
+        }
+#endif
+        throw new ArgumentException(message);
       }
     }     
   }