Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System.Net.Http / System.Net.Http / HttpContent.cs
index 619e0b834a1a0e45aa6bea39868918e303add62b..ad068a598d41e04b27f727d85cfaf8d70aeaf29b 100644 (file)
 //
 
 using System.Net.Http.Headers;
+using System.IO;
+using System.Threading.Tasks;
+using System.Text;
 
 namespace System.Net.Http
 {
        public abstract class HttpContent : IDisposable
        {
+               sealed class FixedMemoryStream : MemoryStream
+               {
+                       readonly long maxSize;
+                       
+                       public FixedMemoryStream (long maxSize)
+                               : base ()
+                       {
+                               this.maxSize = maxSize;
+                       }
+                       
+                       void CheckOverflow (int count)
+                       {
+                               if (Length + count > maxSize)
+                                       throw new HttpRequestException (string.Format ("Cannot write more bytes to the buffer than the configured maximum buffer size: {0}", maxSize));
+                       }
+                       
+                       public override void WriteByte (byte value)
+                       {
+                               CheckOverflow (1);
+                               base.WriteByte (value);
+                       }
+                       
+                       public override void Write (byte[] buffer, int offset, int count)
+                       {
+                               CheckOverflow (count);
+                               base.Write (buffer, offset, count);
+                       }
+               }
+               
+               FixedMemoryStream buffer;
+               Stream stream;
+               bool disposed;
+               HttpContentHeaders headers;
+
                public HttpContentHeaders Headers {
                        get {
-                               return new HttpContentHeaders ();
+                               return headers ?? (headers = new HttpContentHeaders (this));
                        }
                }
+
+               public Task CopyToAsync (Stream stream)
+               {
+                       return CopyToAsync (stream, null);
+               }
+
+               public Task CopyToAsync (Stream stream, TransportContext context)
+               {
+                       if (stream == null)
+                               throw new ArgumentNullException ("stream");
+
+                       return SerializeToStreamAsync (stream, context);
+               }
+
+               protected async virtual Task<Stream> CreateContentReadStreamAsync ()
+               {
+                       await LoadIntoBufferAsync ().ConfigureAwait (false);
+                       return buffer;
+               }
                
+               static FixedMemoryStream CreateFixedMemoryStream (long maxBufferSize)
+               {
+                       return new FixedMemoryStream (maxBufferSize);
+               }
+
                public void Dispose ()
                {
                        Dispose (true);
@@ -45,11 +106,66 @@ namespace System.Net.Http
                
                protected virtual void Dispose (bool disposing)
                {
+                       if (disposing && !disposed) {
+                               disposed = true;
+
+                               if (buffer != null)
+                                       buffer.Dispose ();
+                       }
+               }
+
+               public Task LoadIntoBufferAsync ()
+               {
+                       return LoadIntoBufferAsync (65536);
                }
 
-               public string ReadAsString ()
+               public async Task LoadIntoBufferAsync (long maxBufferSize)
                {
-                       return null;
+                       if (disposed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (buffer != null)
+                               return;
+
+                       buffer = CreateFixedMemoryStream (maxBufferSize);
+                       await SerializeToStreamAsync (buffer, null).ConfigureAwait (false);
+                       buffer.Seek (0, SeekOrigin.Begin);
+               }
+               
+               public async Task<Stream> ReadAsStreamAsync ()
+               {
+                       if (disposed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (stream == null)
+                               stream = await CreateContentReadStreamAsync ().ConfigureAwait (false);
+
+                       return stream;
                }
+
+               public async Task<byte[]> ReadAsByteArrayAsync ()
+               {
+                       await LoadIntoBufferAsync ().ConfigureAwait (false);
+                       return buffer.ToArray ();
+               }
+
+               public async Task<string> ReadAsStringAsync ()
+               {
+                       await LoadIntoBufferAsync ().ConfigureAwait (false);
+                       if (buffer.Length == 0)
+                               return string.Empty;
+
+                       Encoding encoding;
+                       if (headers != null && headers.ContentType != null && headers.ContentType.CharSet != null) {
+                               encoding = Encoding.GetEncoding (headers.ContentType.CharSet);
+                       } else {
+                               encoding = Encoding.UTF8;
+                       }
+
+                       return encoding.GetString (buffer.GetBuffer (), 0, (int) buffer.Length);
+               }
+
+               protected internal abstract Task SerializeToStreamAsync (Stream stream, TransportContext context);
+               protected internal abstract bool TryComputeLength (out long length);
        }
 }