Reader/Writer implementations changed to use static factories
diff --git a/src/ProtocolBuffers/Serialization/DictionaryReader.cs b/src/ProtocolBuffers/Serialization/DictionaryReader.cs
index f8ef1ed..d6e5c18 100644
--- a/src/ProtocolBuffers/Serialization/DictionaryReader.cs
+++ b/src/ProtocolBuffers/Serialization/DictionaryReader.cs
@@ -64,7 +64,7 @@
                 try 

                 {

                     if (obj is IConvertible)

-                        value = (T)Convert.ChangeType(obj, typeof(T));

+                        value = (T)Convert.ChangeType(obj, typeof(T), System.Globalization.CultureInfo.InvariantCulture);

                     else

                         value = (T)obj;

                 }

@@ -186,8 +186,17 @@
             object[] array = null;

             if (GetValue(ref array))

             {

-                foreach (T item in array)

-                    items.Add(item);

+                if (typeof(T) == typeof(ByteString))

+                {

+                    ICollection<ByteString> output = (ICollection<ByteString>)items;

+                    foreach (byte[] item in array)

+                        output.Add(ByteString.CopyFrom(item));

+                }

+                else

+                {

+                    foreach (T item in array)

+                        items.Add(item);

+                }

                 return true;

             }

             return false;

diff --git a/src/ProtocolBuffers/Serialization/JsonFormatReader.cs b/src/ProtocolBuffers/Serialization/JsonFormatReader.cs
index e9df913..2808ff5 100644
--- a/src/ProtocolBuffers/Serialization/JsonFormatReader.cs
+++ b/src/ProtocolBuffers/Serialization/JsonFormatReader.cs
@@ -10,7 +10,7 @@
     /// </summary>

     public class JsonFormatReader : AbstractTextReader

     {

-        private readonly JsonTextCursor _input;

+        private readonly JsonCursor _input;

         private readonly Stack<int> _stopChar;

 

         enum ReaderState { Start, BeginValue, EndValue, BeginObject, BeginArray }

@@ -18,27 +18,43 @@
         ReaderState _state;

 

         /// <summary>

-        /// Constructs a JsonFormatReader to parse Json into a message

+        /// Constructs a JsonFormatReader to parse Json into a message, this method does not use text encoding, all bytes MUST

+        /// represent ASCII character values.

         /// </summary>

-        public JsonFormatReader(string jsonText)

-        {

-            _input = new JsonTextCursor(jsonText.ToCharArray());

-            _stopChar = new Stack<int>();

-            _stopChar.Push(-1);

-            _state = ReaderState.Start;

-        }

+        public static JsonFormatReader CreateInstance(Stream stream) { return new JsonFormatReader(JsonCursor.CreateInstance(stream)); }

+        /// <summary>

+        /// Constructs a JsonFormatReader to parse Json into a message, this method does not use text encoding, all bytes MUST

+        /// represent ASCII character values.

+        /// </summary>

+        public static JsonFormatReader CreateInstance(byte[] bytes) { return new JsonFormatReader(JsonCursor.CreateInstance(bytes)); }

         /// <summary>

         /// Constructs a JsonFormatReader to parse Json into a message

         /// </summary>

-        public JsonFormatReader(TextReader input)

+        public static JsonFormatReader CreateInstance(string jsonText) { return new JsonFormatReader(JsonCursor.CreateInstance(jsonText)); }

+        /// <summary>

+        /// Constructs a JsonFormatReader to parse Json into a message

+        /// </summary>

+        public static JsonFormatReader CreateInstance(TextReader input) { return new JsonFormatReader(JsonCursor.CreateInstance(input)); }

+

+        /// <summary>

+        /// Constructs a JsonFormatReader to parse Json into a message

+        /// </summary>

+        internal JsonFormatReader(JsonCursor input)

         {

-            _input = new JsonTextCursor(input);

+            _input = input;

             _stopChar = new Stack<int>();

             _stopChar.Push(-1);

             _state = ReaderState.Start;

         }

 

         /// <summary>

+        /// Constructs a JsonFormatReader to parse Json into a message

+        /// </summary>

+        protected JsonFormatReader(TextReader input)

+            : this(JsonCursor.CreateInstance(input))

+        { }

+

+        /// <summary>

         /// Returns true if the reader is currently on an array element

         /// </summary>

         public bool IsArrayMessage { get { return _input.NextChar == '['; } }

@@ -115,18 +131,18 @@
         protected override bool ReadAsText(ref string value, Type typeInfo)

         {

             object temp;

-            JsonTextCursor.JsType type = _input.ReadVariant(out temp);

+            JsonCursor.JsType type = _input.ReadVariant(out temp);

             _state = ReaderState.EndValue;

 

-            _input.Assert(type != JsonTextCursor.JsType.Array && type != JsonTextCursor.JsType.Object, "Encountered {0} while expecting {1}", type, typeInfo);

-            if (type == JsonTextCursor.JsType.Null)

+            _input.Assert(type != JsonCursor.JsType.Array && type != JsonCursor.JsType.Object, "Encountered {0} while expecting {1}", type, typeInfo);

+            if (type == JsonCursor.JsType.Null)

                 return false;

-            if (type == JsonTextCursor.JsType.True) value = "1";

-            else if (type == JsonTextCursor.JsType.False) value = "0";

+            if (type == JsonCursor.JsType.True) value = "1";

+            else if (type == JsonCursor.JsType.False) value = "0";

             else value = temp as string;

 

             //exponent representation of integer number:

-            if (value != null && type == JsonTextCursor.JsType.Number &&

+            if (value != null && type == JsonCursor.JsType.Number &&

                 (typeInfo != typeof(double) && typeInfo != typeof(float)) &&

                 value.IndexOf("e", StringComparison.OrdinalIgnoreCase) > 0)

             {

diff --git a/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs b/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
index 0baf6ca..b205752 100644
--- a/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
+++ b/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
@@ -1,6 +1,7 @@
 using System;

 using System.Collections.Generic;

 using System.IO;

+using System.Text;

 using Google.ProtocolBuffers.Descriptors;

 

 namespace Google.ProtocolBuffers.Serialization

@@ -10,81 +11,178 @@
     /// you may also use the XmlFormatWriter with an XmlWriter created by the

     /// <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory">JsonReaderWriterFactory</see>.

     /// </summary>

-    public class JsonFormatWriter : AbstractTextWriter

+    public abstract class JsonFormatWriter : AbstractTextWriter

     {

-        private readonly char[] _buffer;

-        private readonly TextWriter _output;

-        private readonly List<int> _counter;

-        private bool _isArray;

-        int _bufferPos;

-        /// <summary>

-        /// Constructs a JsonFormatWriter to output to a new instance of a StringWriter, use

-        /// the ToString() member to extract the final Json on completion.

-        /// </summary>

-        public JsonFormatWriter() : this(new StringWriter()) { }

-        /// <summary>

-        /// Constructs a JsonFormatWriter to output to the given text writer

-        /// </summary>

-        public JsonFormatWriter(TextWriter output)

+        #region buffering implementations

+        private class JsonTextWriter : JsonFormatWriter

         {

-            _buffer = new char[4096];

-            _bufferPos = 0;

-            _output = output;

-            _counter = new List<int>();

-            _counter.Add(0);

-        }

+            private readonly char[] _buffer;

+            private TextWriter _output;

+            int _bufferPos;

 

-

-        private void WriteToOutput(string format, params object[] args)

-        { WriteToOutput(String.Format(format, args)); }

-

-        private void WriteToOutput(string text)

-        { WriteToOutput(text.ToCharArray(), 0, text.Length); }

-

-        private void WriteToOutput(char[] chars, int offset, int len)

-        {

-            if (_bufferPos + len >= _buffer.Length)

-                Flush();

-            if (len < _buffer.Length)

+            public JsonTextWriter(TextWriter output)

             {

-                if (len <= 12)

+                _buffer = new char[4096];

+                _bufferPos = 0;

+                _output = output;

+                _counter.Add(0);

+            }

+

+            /// <summary>

+            /// Returns the output of TextWriter.ToString() where TextWriter is the ctor argument.

+            /// </summary>

+            public override string ToString()

+            {

+                Flush();

+

+                if (_output != null)

+                    return _output.ToString();

+

+                return new String(_buffer, 0, _bufferPos);

+            }

+

+            protected override void WriteToOutput(char[] chars, int offset, int len)

+            {

+                if (_bufferPos + len >= _buffer.Length)

                 {

-                    int stop = offset + len;

-                    for (int i = offset; i < stop; i++)

-                        _buffer[_bufferPos++] = chars[i];

+                    if (_output == null)

+                        _output = new StringWriter(new System.Text.StringBuilder(_buffer.Length * 2 + len));

+                    Flush();

+                }

+

+                if (len < _buffer.Length)

+                {

+                    if (len <= 12)

+                    {

+                        int stop = offset + len;

+                        for (int i = offset; i < stop; i++)

+                            _buffer[_bufferPos++] = chars[i];

+                    }

+                    else

+                    {

+                        Buffer.BlockCopy(chars, offset << 1, _buffer, _bufferPos << 1, len << 1);

+                        _bufferPos += len;

+                    }

+                }

+                else

+                    _output.Write(chars, offset, len);

+            }

+

+            protected override void WriteToOutput(char ch)

+            {

+                if (_bufferPos >= _buffer.Length)

+                    Flush();

+                _buffer[_bufferPos++] = ch;

+            }

+

+            public override void Flush()

+            {

+                if (_bufferPos > 0 && _output != null)

+                {

+                    _output.Write(_buffer, 0, _bufferPos);

+                    _bufferPos = 0;

+                }

+                base.Flush();

+            }

+        }

+        private class JsonStreamWriter : JsonFormatWriter

+        {

+#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35

+            static readonly Encoding Encoding = Encoding.UTF8;

+#else

+            static readonly Encoding Encoding = Encoding.ASCII;

+#endif

+            private readonly byte[] _buffer;

+            private Stream _output;

+            int _bufferPos;

+

+            public JsonStreamWriter(Stream output)

+            {

+                _buffer = new byte[8192];

+                _bufferPos = 0;

+                _output = output;

+                _counter.Add(0);

+            }

+

+            protected override void WriteToOutput(char[] chars, int offset, int len)

+            {

+                if (_bufferPos + len >= _buffer.Length)

+                    Flush();

+

+                if (len < _buffer.Length)

+                {

+                    if (len <= 12)

+                    {

+                        int stop = offset + len;

+                        for (int i = offset; i < stop; i++)

+                            _buffer[_bufferPos++] = (byte)chars[i];

+                    }

+                    else

+                    {

+                        _bufferPos += Encoding.GetBytes(chars, offset, len, _buffer, _bufferPos);

+                    }

                 }

                 else

                 {

-                    Buffer.BlockCopy(chars, offset << 1, _buffer, _bufferPos << 1, len << 1);

-                    _bufferPos += len;

+                    byte[] temp = Encoding.GetBytes(chars, offset, len);

+                    _output.Write(temp, 0, temp.Length);

                 }

             }

-            else

-                _output.Write(chars, offset, len);

-        }

 

-        private void WriteToOutput(char ch)

-        {

-            if (_bufferPos >= _buffer.Length)

-                Flush();

-            _buffer[_bufferPos++] = ch;

-        }

-

-        public override void Flush()

-        {

-            if (_bufferPos > 0)

+            protected override void WriteToOutput(char ch)

             {

-                _output.Write(_buffer, 0, _bufferPos);

-                _bufferPos = 0;

+                if (_bufferPos >= _buffer.Length)

+                    Flush();

+                _buffer[_bufferPos++] = (byte)ch;

             }

-            base.Flush();

+

+            public override void Flush()

+            {

+                if (_bufferPos > 0 && _output != null)

+                {

+                    _output.Write(_buffer, 0, _bufferPos);

+                    _bufferPos = 0;

+                }

+                base.Flush();

+            }

+        }

+        #endregion

+

+        private readonly List<int> _counter;

+        private bool _isArray;

+        /// <summary>

+        /// Constructs a JsonFormatWriter, use the ToString() member to extract the final Json on completion.

+        /// </summary>

+        protected JsonFormatWriter()

+        {

+            _counter = new List<int>();

         }

 

         /// <summary>

-        /// Returns the output of TextWriter.ToString() where TextWriter is the ctor argument.

+        /// Constructs a JsonFormatWriter, use ToString() to extract the final output

         /// </summary>

-        public override string ToString()

-        { Flush(); return _output.ToString(); }

+        public static JsonFormatWriter CreateInstance() { return new JsonTextWriter(null); }

+            

+        /// <summary>

+        /// Constructs a JsonFormatWriter to output to the given text writer

+        /// </summary>

+        public static JsonFormatWriter CreateInstance(TextWriter output) { return new JsonTextWriter(output); }

+

+        /// <summary>

+        /// Constructs a JsonFormatWriter to output to the given stream

+        /// </summary>

+        public static JsonFormatWriter CreateInstance(Stream output) { return new JsonStreamWriter(output); }

+

+        /// <summary> Write to the output stream </summary>

+        protected void WriteToOutput(string format, params object[] args)

+        { WriteToOutput(String.Format(format, args)); }

+        /// <summary> Write to the output stream </summary>

+        protected void WriteToOutput(string text)

+        { WriteToOutput(text.ToCharArray(), 0, text.Length); }

+        /// <summary> Write to the output stream </summary>

+        protected abstract void WriteToOutput(char ch);

+        /// <summary> Write to the output stream </summary>

+        protected abstract void WriteToOutput(char[] chars, int offset, int len);

 

         /// <summary> Sets the output formatting to use Environment.NewLine with 4-character indentions </summary>

         public JsonFormatWriter Formatted()

diff --git a/src/ProtocolBuffers/Serialization/JsonTextCursor.cs b/src/ProtocolBuffers/Serialization/JsonTextCursor.cs
index 6a8652c..a0b468f 100644
--- a/src/ProtocolBuffers/Serialization/JsonTextCursor.cs
+++ b/src/ProtocolBuffers/Serialization/JsonTextCursor.cs
@@ -9,52 +9,115 @@
     /// <summary>

     /// JSon Tokenizer used by JsonFormatReader

     /// </summary>

-    class JsonTextCursor

+    abstract class JsonCursor

     {

         public enum JsType { String, Number, Object, Array, True, False, Null }

 

-        private readonly char[] _buffer;

-        private int _bufferPos;

-        private readonly TextReader _input;

+        #region Buffering implementations

+        class JsonStreamCursor : JsonCursor

+        {

+            private readonly byte[] _buffer;

+            private int _bufferPos;

+            private readonly Stream _input;

+

+            public JsonStreamCursor(Stream input)

+            {

+                _input = input;

+                _next = _input.ReadByte();

+            }

+            public JsonStreamCursor(byte[] input)

+            {

+                _input = null;

+                _buffer = input;

+                _next = _buffer[_bufferPos];

+            }

+

+            protected override int Peek()

+            {

+                if (_input != null)

+                    return _next;

+                else if (_bufferPos < _buffer.Length)

+                    return _buffer[_bufferPos];

+                else

+                    return -1;

+            }

+

+            protected override int Read()

+            {

+                if (_input != null)

+                {

+                    int result = _next;

+                    _next = _input.ReadByte();

+                    return result;

+                }

+                else if (_bufferPos < _buffer.Length)

+                    return _buffer[_bufferPos++];

+                else

+                    return -1;

+            }

+        }

+

+        class JsonTextCursor : JsonCursor

+        {

+            private readonly char[] _buffer;

+            private int _bufferPos;

+            private readonly TextReader _input;

+

+            public JsonTextCursor(char[] input)

+            {

+                _input = null;

+                _buffer = input;

+                _bufferPos = 0;

+                _next = Peek();

+            }

+

+            public JsonTextCursor(TextReader input)

+            {

+                _input = input;

+                _next = Peek();

+            }

+

+            protected override int Peek()

+            {

+                if (_input != null)

+                    return _input.Peek();

+                else if (_bufferPos < _buffer.Length)

+                    return _buffer[_bufferPos];

+                else

+                    return -1;

+            }

+

+            protected override int Read()

+            {

+                if (_input != null)

+                    return _input.Read();

+                else if (_bufferPos < _buffer.Length)

+                    return _buffer[_bufferPos++];

+                else

+                    return -1;

+            }

+        }

+        #endregion

+

+        protected int _next;

         private int _lineNo, _linePos;

 

-        public JsonTextCursor(char[] input)

+        public static JsonCursor CreateInstance(byte[] input) { return new JsonStreamCursor(input); }

+        public static JsonCursor CreateInstance(Stream input) { return new JsonStreamCursor(input); }

+        public static JsonCursor CreateInstance(string input) { return new JsonTextCursor(input.ToCharArray()); }

+        public static JsonCursor CreateInstance(TextReader input) { return new JsonTextCursor(input); }

+

+        protected JsonCursor()

         {

-            _input = null;

-            _buffer = input;

-            _bufferPos = 0;

-            _next = Peek();

             _lineNo = 1;

+            _linePos = 0;

         }

+        

+        /// <summary>Returns the next character without actually 'reading' it</summary>

+        protected abstract int Peek();

+        /// <summary>Reads the next character in the input</summary>

+        protected abstract int Read();

 

-        public JsonTextCursor(TextReader input)

-        {

-            _input = input;

-            _next = Peek();

-            _lineNo = 1;

-        }

-

-        private int Peek()

-        {

-            if (_input != null)

-                return _input.Peek();

-            else if (_bufferPos < _buffer.Length)

-                return _buffer[_bufferPos];

-            else

-                return -1;

-        }

-

-        private int Read()

-        {

-            if (_input != null)

-                return _input.Read();

-            else if (_bufferPos < _buffer.Length)

-                return _buffer[_bufferPos++];

-            else

-                return -1;

-        }

-

-        int _next;

         public Char NextChar { get { SkipWhitespace(); return (char)_next; } }

 

         #region Assert(...)

@@ -62,8 +125,8 @@
         private string CharDisplay(int ch)

         {

             return ch == -1 ? "EOF" :

-                                        (ch > 32 && ch < 127) ? String.Format("'{0}'", (char)ch) :

-                                                                                                     String.Format("'\\u{0:x4}'", ch);

+                (ch > 32 && ch < 127) ? String.Format("'{0}'", (char)ch) :

+                String.Format("'\\u{0:x4}'", ch);

         }

         [System.Diagnostics.DebuggerNonUserCode]

         private void Assert(bool cond, char expected)

diff --git a/src/ProtocolBuffers/Serialization/XmlFormatReader.cs b/src/ProtocolBuffers/Serialization/XmlFormatReader.cs
index 671490e..241c554 100644
--- a/src/ProtocolBuffers/Serialization/XmlFormatReader.cs
+++ b/src/ProtocolBuffers/Serialization/XmlFormatReader.cs
@@ -25,33 +25,41 @@
         /// <summary>

         /// Constructs the XmlFormatReader using the stream provided as the xml

         /// </summary>

-        public XmlFormatReader(Stream input) : this(XmlReader.Create(input, DefaultSettings)) { }

+        public static XmlFormatReader CreateInstance(byte[] input) { return new XmlFormatReader(XmlReader.Create(new MemoryStream(input, false), DefaultSettings)); }

+        /// <summary>

+        /// Constructs the XmlFormatReader using the stream provided as the xml

+        /// </summary>

+        public static XmlFormatReader CreateInstance(Stream input) { return new XmlFormatReader(XmlReader.Create(input, DefaultSettings)); }

         /// <summary>

         /// Constructs the XmlFormatReader using the string provided as the xml to be read

         /// </summary>

-        public XmlFormatReader(String input) : this(XmlReader.Create(new StringReader(input))) { }

+        public static XmlFormatReader CreateInstance(String input) { return new XmlFormatReader(XmlReader.Create(new StringReader(input), DefaultSettings)); }

         /// <summary>

         /// Constructs the XmlFormatReader using the xml in the TextReader

         /// </summary>

-        public XmlFormatReader(TextReader input) : this(XmlReader.Create(input)) { }

+        public static XmlFormatReader CreateInstance(TextReader input) { return new XmlFormatReader(XmlReader.Create(input, DefaultSettings)); }

         /// <summary>

         /// Constructs the XmlFormatReader with the XmlReader

         /// </summary>

-        public XmlFormatReader(XmlReader input) : this(input, XmlReaderOptions.None) { }

+        public static XmlFormatReader CreateInstance(XmlReader input) { return new XmlFormatReader(input); }

         /// <summary>

         /// Constructs the XmlFormatReader with the XmlReader and options

         /// </summary>

-        public XmlFormatReader(XmlReader input, XmlReaderOptions options)

+        protected XmlFormatReader(XmlReader input)

         {

             _input = input;

             _rootElementName = DefaultRootElementName;

-            Options = options;

+            Options = XmlReaderOptions.None;

         }

         

         /// <summary>

         /// Gets or sets the options to use when reading the xml

         /// </summary>

         public XmlReaderOptions Options { get; set; }

+        /// <summary>

+        /// Sets the options to use while generating the XML

+        /// </summary>

+        public XmlFormatReader SetOptions(XmlReaderOptions options) { Options = options; return this; }

 

         /// <summary>

         /// Gets or sets the default element name to use when using the Merge&lt;TBuilder>()

@@ -64,7 +72,7 @@
 

         private XmlFormatReader CloneWith(XmlReader rdr)

         {

-            return new XmlFormatReader(rdr, Options);

+            return new XmlFormatReader(rdr).SetOptions(Options);

         }

         private void NextElement()

         {

diff --git a/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs b/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
index b5dbf5f..2bb4f15 100644
--- a/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
+++ b/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
@@ -1,5 +1,6 @@
 using System;

 using System.IO;

+using System.Text;

 using System.Xml;

 using Google.ProtocolBuffers.Descriptors;

 

@@ -17,23 +18,29 @@
         private readonly XmlWriter _output;

         private string _rootElementName;

 

-        static XmlWriterSettings DefaultSettings

+        static XmlWriterSettings DefaultSettings(Encoding encoding)

         {

-            get { return new XmlWriterSettings() {CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize}; }

+            return new XmlWriterSettings() { CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize, Encoding = encoding };

         }

 

         /// <summary>

         /// Constructs the XmlFormatWriter to write to the given TextWriter

         /// </summary>

-        public XmlFormatWriter(TextWriter output) : this(XmlWriter.Create(output, DefaultSettings)) { }

+        public static XmlFormatWriter CreateInstance(TextWriter output) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(output.Encoding))); }

         /// <summary>

         /// Constructs the XmlFormatWriter to write to the given stream

         /// </summary>

-        public XmlFormatWriter(Stream output) : this(XmlWriter.Create(output, DefaultSettings)) { }

+        public static XmlFormatWriter CreateInstance(Stream output) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(Encoding.UTF8))); }

+        /// <summary>

+        /// Constructs the XmlFormatWriter to write to the given stream

+        /// </summary>

+        public static XmlFormatWriter CreateInstance(Stream output, Encoding encoding) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(encoding))); }

         /// <summary>

         /// Constructs the XmlFormatWriter to write to the given XmlWriter

         /// </summary>

-        public XmlFormatWriter(XmlWriter output)

+        public static XmlFormatWriter CreateInstance(XmlWriter output) { return new XmlFormatWriter(output); }

+

+        protected XmlFormatWriter(XmlWriter output)

         {

             _output = output;

             _rootElementName = DefaultRootElementName;

@@ -61,6 +68,10 @@
         /// Gets or sets the options to use while generating the XML

         /// </summary>

         public XmlWriterOptions Options { get; set; }

+        /// <summary>

+        /// Sets the options to use while generating the XML

+        /// </summary>

+        public XmlFormatWriter SetOptions(XmlWriterOptions options) { Options = options; return this; }

 

         private bool TestOption(XmlWriterOptions option) { return (Options & option) != 0; }