blob: 270af64bf2a68911c522374fae2d6523c3941b1e [file] [log] [blame]
using System;
using System.IO;
using System.Xml;
using System.Text;
namespace Google.ProtocolBuffers.Serialization.Http
{
/// <summary>
/// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type.
/// </summary>
public static class MessageFormatFactory
{
/// <summary>
/// Constructs an ICodedInputStream from the input stream based on the contentType provided
/// </summary>
/// <param name="options">Options specific to reading this message and/or content type</param>
/// <param name="contentType">The mime type of the input stream content</param>
/// <param name="input">The stream to read the message from</param>
/// <returns>The ICodedInputStream that can be given to the IBuilder.MergeFrom(...) method</returns>
public static ICodedInputStream CreateInputStream(MessageFormatOptions options, string contentType, Stream input)
{
ICodedInputStream codedInput = ContentTypeToInputStream(contentType, options, input);
if (codedInput is XmlFormatReader)
{
XmlFormatReader reader = (XmlFormatReader)codedInput;
reader.RootElementName = options.XmlReaderRootElementName;
reader.Options = options.XmlReaderOptions;
}
return codedInput;
}
/// <summary>
/// Writes the message instance to the stream using the content type provided
/// </summary>
/// <param name="options">Options specific to writing this message and/or content type</param>
/// <param name="contentType">The mime type of the content to be written</param>
/// <param name="output">The stream to write the message to</param>
/// <remarks> If you do not dispose of ICodedOutputStream some formats may yield incomplete output </remarks>
public static ICodedOutputStream CreateOutputStream(MessageFormatOptions options, string contentType, Stream output)
{
ICodedOutputStream codedOutput = ContentTypeToOutputStream(contentType, options, output);
if (codedOutput is JsonFormatWriter)
{
JsonFormatWriter writer = (JsonFormatWriter)codedOutput;
if (options.FormattedOutput)
{
writer.Formatted();
}
}
else if (codedOutput is XmlFormatWriter)
{
XmlFormatWriter writer = (XmlFormatWriter)codedOutput;
if (options.FormattedOutput)
{
XmlWriterSettings settings = new XmlWriterSettings()
{
CheckCharacters = false,
NewLineHandling = NewLineHandling.Entitize,
OmitXmlDeclaration = true,
Encoding = new UTF8Encoding(false),
Indent = true,
IndentChars = " ",
};
// Don't know how else to change xml writer options?
codedOutput = writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
}
writer.RootElementName = options.XmlWriterRootElementName;
writer.Options = options.XmlWriterOptions;
}
return codedOutput;
}
private static ICodedInputStream ContentTypeToInputStream(string contentType, MessageFormatOptions options, Stream input)
{
contentType = (contentType ?? String.Empty).Split(';')[0].Trim();
CodedInputBuilder factory;
if(!options.MimeInputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
{
if(String.IsNullOrEmpty(options.DefaultContentType) ||
!options.MimeInputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
{
throw new ArgumentOutOfRangeException("contentType");
}
}
return factory(input);
}
private static ICodedOutputStream ContentTypeToOutputStream(string contentType, MessageFormatOptions options, Stream output)
{
contentType = (contentType ?? String.Empty).Split(';')[0].Trim();
CodedOutputBuilder factory;
if (!options.MimeOutputTypesReadOnly.TryGetValue(contentType, out factory) || factory == null)
{
if (String.IsNullOrEmpty(options.DefaultContentType) ||
!options.MimeOutputTypesReadOnly.TryGetValue(options.DefaultContentType, out factory) || factory == null)
{
throw new ArgumentOutOfRangeException("contentType");
}
}
return factory(output);
}
}
}