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); | |
} | |
} | |
} |