Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
247c7534
Commit
247c7534
authored
Sep 30, 2011
by
csharptest
Committed by
rogerk
Sep 30, 2011
Browse files
Options
Browse Files
Download
Plain Diff
merged issue-24
parents
b6a14572
06963f90
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1801 additions
and
114 deletions
+1801
-114
AbstractReader.cs
src/ProtocolBuffers.Serialization/AbstractReader.cs
+10
-6
AbstractTextReader.cs
src/ProtocolBuffers.Serialization/AbstractTextReader.cs
+0
-4
AbstractWriter.cs
src/ProtocolBuffers.Serialization/AbstractWriter.cs
+19
-16
DictionaryReader.cs
src/ProtocolBuffers.Serialization/DictionaryReader.cs
+13
-1
DictionaryWriter.cs
src/ProtocolBuffers.Serialization/DictionaryWriter.cs
+14
-1
FormUrlEncodedReader.cs
...rotocolBuffers.Serialization/Http/FormUrlEncodedReader.cs
+163
-0
MessageFormatFactory.cs
...rotocolBuffers.Serialization/Http/MessageFormatFactory.cs
+154
-0
MessageFormatOptions.cs
...rotocolBuffers.Serialization/Http/MessageFormatOptions.cs
+168
-0
ServiceExtensions.cs
src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs
+34
-0
JsonFormatReader.cs
src/ProtocolBuffers.Serialization/JsonFormatReader.cs
+22
-5
JsonFormatWriter.cs
src/ProtocolBuffers.Serialization/JsonFormatWriter.cs
+24
-4
ProtocolBuffers.Serialization.csproj
...uffers.Serialization/ProtocolBuffers.Serialization.csproj
+4
-0
XmlFormatReader.cs
src/ProtocolBuffers.Serialization/XmlFormatReader.cs
+92
-54
XmlFormatWriter.cs
src/ProtocolBuffers.Serialization/XmlFormatWriter.cs
+57
-20
JsonCompatibilityTests.cs
...tocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs
+18
-0
XmlCompatibilityTests.cs
...otocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs
+22
-0
AssemblyInfo.cs
src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
+1
-1
ProtocolBuffers.Test.csproj
src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+3
-0
TestMimeMessageFormats.cs
src/ProtocolBuffers.Test/TestMimeMessageFormats.cs
+265
-0
TestReaderForUrlEncoded.cs
src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs
+84
-0
TestRpcForMimeTypes.cs
src/ProtocolBuffers.Test/TestRpcForMimeTypes.cs
+387
-0
TestWriterFormatJson.cs
src/ProtocolBuffers.Test/TestWriterFormatJson.cs
+86
-0
TestWriterFormatXml.cs
src/ProtocolBuffers.Test/TestWriterFormatXml.cs
+119
-2
CodedInputStream.cs
src/ProtocolBuffers/CodedInputStream.cs
+3
-0
CodedOutputStream.cs
src/ProtocolBuffers/CodedOutputStream.cs
+3
-0
ICodedInputStream.cs
src/ProtocolBuffers/ICodedInputStream.cs
+18
-0
ICodedOutputStream.cs
src/ProtocolBuffers/ICodedOutputStream.cs
+18
-0
No files found.
src/ProtocolBuffers.Serialization/AbstractReader.cs
View file @
247c7534
...
@@ -17,12 +17,6 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -17,12 +17,6 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> Constructs a new reader </summary>
/// <summary> Constructs a new reader </summary>
protected
AbstractReader
()
{
MaxDepth
=
DefaultMaxDepth
;
}
protected
AbstractReader
()
{
MaxDepth
=
DefaultMaxDepth
;
}
/// <summary> Constructs a new child reader </summary>
protected
AbstractReader
(
AbstractReader
copyFrom
)
{
_depth
=
copyFrom
.
_depth
+
1
;
MaxDepth
=
copyFrom
.
MaxDepth
;
}
/// <summary> Gets or sets the maximum recursion depth allowed </summary>
/// <summary> Gets or sets the maximum recursion depth allowed </summary>
public
int
MaxDepth
{
get
;
set
;
}
public
int
MaxDepth
{
get
;
set
;
}
...
@@ -112,6 +106,16 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -112,6 +106,16 @@ namespace Google.ProtocolBuffers.Serialization
/// Merges the input stream into the provided IBuilderLite
/// Merges the input stream into the provided IBuilderLite
/// </summary>
/// </summary>
protected
abstract
bool
ReadMessage
(
IBuilderLite
builder
,
ExtensionRegistry
registry
);
protected
abstract
bool
ReadMessage
(
IBuilderLite
builder
,
ExtensionRegistry
registry
);
/// <summary>
/// Reads the root-message preamble specific to this formatter
/// </summary>
public
abstract
void
ReadMessageStart
();
/// <summary>
/// Reads the root-message close specific to this formatter
/// </summary>
public
abstract
void
ReadMessageEnd
();
/// <summary>
/// <summary>
/// Merges the input stream into the provided IBuilderLite
/// Merges the input stream into the provided IBuilderLite
...
...
src/ProtocolBuffers.Serialization/AbstractTextReader.cs
View file @
247c7534
...
@@ -11,10 +11,6 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -11,10 +11,6 @@ namespace Google.ProtocolBuffers.Serialization
{
{
/// <summary> Constructs a new reader </summary>
/// <summary> Constructs a new reader </summary>
protected
AbstractTextReader
()
{
}
protected
AbstractTextReader
()
{
}
/// <summary> Constructs a new child reader </summary>
protected
AbstractTextReader
(
AbstractTextReader
copyFrom
)
:
base
(
copyFrom
)
{
}
/// <summary>
/// <summary>
/// Reads a typed field as a string
/// Reads a typed field as a string
...
...
src/ProtocolBuffers.Serialization/AbstractWriter.cs
View file @
247c7534
...
@@ -12,36 +12,39 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -12,36 +12,39 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary>
/// <summary>
/// Provides a base class for writers that performs some basic type dispatching
/// Provides a base class for writers that performs some basic type dispatching
/// </summary>
/// </summary>
public
abstract
class
AbstractWriter
:
ICodedOutputStream
,
IDisposable
public
abstract
class
AbstractWriter
:
ICodedOutputStream
{
{
/// <summary>
/// <summary>
///
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
Completes any pending write operations
/// </summary>
/// </summary>
public
v
oid
Dispose
()
public
v
irtual
void
Flush
()
{
{
GC
.
SuppressFinalize
(
this
);
Flush
();
Dispose
(
true
);
}
}
/// <summary>
/// <summary>
///
Completes any pending write operations
///
Writes the message to the the formatted stream.
/// </summary>
/// </summary>
public
virtual
void
Flush
()
public
abstract
void
WriteMessage
(
IMessageLite
message
);
{
}
/// <summary>
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// Used to write any nessary root-message preamble. After this call you can call
/// IMessageLite.MergeTo(...) and complete the message with a call to WriteMessageEnd().
/// These three calls are identical to just calling WriteMessage(message);
/// </summary>
/// </summary>
protected
virtual
void
Dispose
(
bool
disposing
)
/// <example>
{
/// AbstractWriter writer;
}
/// writer.WriteMessageStart();
/// message.WriteTo(writer);
/// writer.WriteMessageEnd();
/// // ... or, but not both ...
/// writer.WriteMessage(message);
/// </example>
public
abstract
void
WriteMessageStart
();
/// <summary>
/// <summary>
///
Writes the message to the the formatted stream.
///
Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary>
/// </summary>
public
abstract
void
WriteMessage
(
IMessageLite
message
);
public
abstract
void
WriteMessage
End
(
);
/// <summary>
/// <summary>
/// Writes a Boolean value
/// Writes a Boolean value
...
...
src/ProtocolBuffers.Serialization/DictionaryReader.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.Globalization
;
using
System.Globalization
;
using
Google.ProtocolBuffers.Descriptors
;
using
Google.ProtocolBuffers.Descriptors
;
...
@@ -22,6 +22,18 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -22,6 +22,18 @@ namespace Google.ProtocolBuffers.Serialization
_ready
=
_input
.
MoveNext
();
_ready
=
_input
.
MoveNext
();
}
}
/// <summary>
/// No-op
/// </summary>
public
override
void
ReadMessageStart
()
{
}
/// <summary>
/// No-op
/// </summary>
public
override
void
ReadMessageEnd
()
{
}
/// <summary>
/// <summary>
/// Merges the contents of stream into the provided message builder
/// Merges the contents of stream into the provided message builder
/// </summary>
/// </summary>
...
...
src/ProtocolBuffers.Serialization/DictionaryWriter.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections
;
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
Google.ProtocolBuffers.Descriptors
;
using
Google.ProtocolBuffers.Descriptors
;
...
@@ -53,6 +53,19 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -53,6 +53,19 @@ namespace Google.ProtocolBuffers.Serialization
message
.
WriteTo
(
this
);
message
.
WriteTo
(
this
);
}
}
/// <summary>
/// No-op
/// </summary>
public
override
void
WriteMessageStart
()
{
}
/// <summary>
/// No-op
/// </summary>
public
override
void
WriteMessageEnd
()
{
}
/// <summary>
/// <summary>
/// Writes a Boolean value
/// Writes a Boolean value
/// </summary>
/// </summary>
...
...
src/ProtocolBuffers.Serialization/Http/FormUrlEncodedReader.cs
0 → 100644
View file @
247c7534
using
System
;
using
System.IO
;
using
System.Text
;
namespace
Google.ProtocolBuffers.Serialization.Http
{
/// <summary>
/// Allows reading messages from a name/value dictionary
/// </summary>
public
class
FormUrlEncodedReader
:
AbstractTextReader
{
private
readonly
TextReader
_input
;
private
string
_fieldName
,
_fieldValue
;
private
bool
_ready
;
/// <summary>
/// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
/// </summary>
FormUrlEncodedReader
(
TextReader
input
)
{
_input
=
input
;
int
ch
=
input
.
Peek
();
if
(
ch
==
'?'
)
{
input
.
Read
();
}
_ready
=
ReadNext
();
}
#
region
CreateInstance
overloads
/// <summary>
/// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
/// </summary>
public
static
FormUrlEncodedReader
CreateInstance
(
Stream
stream
)
{
return
new
FormUrlEncodedReader
(
new
StreamReader
(
stream
,
Encoding
.
UTF8
,
false
));
}
/// <summary>
/// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
/// </summary>
public
static
FormUrlEncodedReader
CreateInstance
(
byte
[]
bytes
)
{
return
new
FormUrlEncodedReader
(
new
StreamReader
(
new
MemoryStream
(
bytes
,
false
),
Encoding
.
UTF8
,
false
));
}
/// <summary>
/// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
/// </summary>
public
static
FormUrlEncodedReader
CreateInstance
(
string
text
)
{
return
new
FormUrlEncodedReader
(
new
StringReader
(
text
));
}
/// <summary>
/// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
/// </summary>
public
static
FormUrlEncodedReader
CreateInstance
(
TextReader
input
)
{
return
new
FormUrlEncodedReader
(
input
);
}
#
endregion
private
bool
ReadNext
()
{
StringBuilder
field
=
new
StringBuilder
(
32
);
StringBuilder
value
=
new
StringBuilder
(
64
);
int
ch
;
while
(-
1
!=
(
ch
=
_input
.
Read
())
&&
ch
!=
'='
&&
ch
!=
'&'
)
{
field
.
Append
((
char
)
ch
);
}
if
(
ch
!=
-
1
&&
ch
!=
'&'
)
{
while
(-
1
!=
(
ch
=
_input
.
Read
())
&&
ch
!=
'&'
)
{
value
.
Append
((
char
)
ch
);
}
}
_fieldName
=
field
.
ToString
();
_fieldValue
=
Uri
.
UnescapeDataString
(
value
.
Replace
(
'+'
,
' '
).
ToString
());
return
!
String
.
IsNullOrEmpty
(
_fieldName
);
}
/// <summary>
/// No-op
/// </summary>
public
override
void
ReadMessageStart
()
{
}
/// <summary>
/// No-op
/// </summary>
public
override
void
ReadMessageEnd
()
{
}
/// <summary>
/// Merges the contents of stream into the provided message builder
/// </summary>
public
override
TBuilder
Merge
<
TBuilder
>(
TBuilder
builder
,
ExtensionRegistry
registry
)
{
builder
.
WeakMergeFrom
(
this
,
registry
);
return
builder
;
}
/// <summary>
/// Causes the reader to skip past this field
/// </summary>
protected
override
void
Skip
()
{
_ready
=
ReadNext
();
}
/// <summary>
/// Peeks at the next field in the input stream and returns what information is available.
/// </summary>
/// <remarks>
/// This may be called multiple times without actually reading the field. Only after the field
/// is either read, or skipped, should PeekNext return a different value.
/// </remarks>
protected
override
bool
PeekNext
(
out
string
field
)
{
field
=
_ready
?
_fieldName
:
null
;
return
field
!=
null
;
}
/// <summary>
/// Returns true if it was able to read a String from the input
/// </summary>
protected
override
bool
ReadAsText
(
ref
string
value
,
Type
typeInfo
)
{
if
(
_ready
)
{
value
=
_fieldValue
;
_ready
=
ReadNext
();
return
true
;
}
return
false
;
}
/// <summary>
/// It's unlikely this will work for anything but text data as bytes UTF8 are transformed to text and back to bytes
/// </summary>
protected
override
ByteString
DecodeBytes
(
string
bytes
)
{
return
ByteString
.
CopyFromUtf8
(
bytes
);
}
/// <summary>
/// Not Supported
/// </summary>
public
override
bool
ReadGroup
(
IBuilderLite
value
,
ExtensionRegistry
registry
)
{
throw
new
NotSupportedException
();
}
/// <summary>
/// Not Supported
/// </summary>
protected
override
bool
ReadMessage
(
IBuilderLite
builder
,
ExtensionRegistry
registry
)
{
throw
new
NotSupportedException
();
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs
0 → 100644
View file @
247c7534
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>
/// Merges the message from the input stream based on the contentType provided
/// </summary>
/// <typeparam name="TBuilder">A type derived from IBuilderLite</typeparam>
/// <param name="builder">An instance of a message builder</param>
/// <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 same builder instance that was supplied in the builder parameter</returns>
public
static
TBuilder
MergeFrom
<
TBuilder
>(
this
TBuilder
builder
,
MessageFormatOptions
options
,
string
contentType
,
Stream
input
)
where
TBuilder
:
IBuilderLite
{
ICodedInputStream
codedInput
=
CreateInputStream
(
options
,
contentType
,
input
);
codedInput
.
ReadMessageStart
();
builder
.
WeakMergeFrom
(
codedInput
,
options
.
ExtensionRegistry
);
codedInput
.
ReadMessageEnd
();
return
builder
;
}
/// <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
=
" "
,
NewLineChars
=
Environment
.
NewLine
,
};
// 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
;
}
/// <summary>
/// Writes the message instance to the stream using the content type provided
/// </summary>
/// <param name="message">An instance of a message</param>
/// <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>
public
static
void
WriteTo
(
this
IMessageLite
message
,
MessageFormatOptions
options
,
string
contentType
,
Stream
output
)
{
ICodedOutputStream
codedOutput
=
CreateOutputStream
(
options
,
contentType
,
output
);
// Output the appropriate message preamble
codedOutput
.
WriteMessageStart
();
// Write the message content to the output
message
.
WriteTo
(
codedOutput
);
// Write the closing message fragment
codedOutput
.
WriteMessageEnd
();
codedOutput
.
Flush
();
}
private
static
ICodedInputStream
ContentTypeToInputStream
(
string
contentType
,
MessageFormatOptions
options
,
Stream
input
)
{
contentType
=
(
contentType
??
String
.
Empty
).
Split
(
';'
)[
0
].
Trim
();
Converter
<
Stream
,
ICodedInputStream
>
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
();
Converter
<
Stream
,
ICodedOutputStream
>
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
);
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs
0 → 100644
View file @
247c7534
using
System
;
using
System.IO
;
using
System.Collections.Generic
;
using
Google.ProtocolBuffers.Collections
;
namespace
Google.ProtocolBuffers.Serialization.Http
{
/// <summary>
/// Defines control information for the various formatting used with HTTP services
/// </summary>
public
class
MessageFormatOptions
{
/// <summary>The mime type for xml content</summary>
/// <remarks>Other valid xml mime types include: application/binary, application/x-protobuf</remarks>
public
const
string
ContentTypeProtoBuffer
=
"application/vnd.google.protobuf"
;
/// <summary>The mime type for xml content</summary>
/// <remarks>Other valid xml mime types include: text/xml</remarks>
public
const
string
ContentTypeXml
=
"application/xml"
;
/// <summary>The mime type for json content</summary>
/// <remarks>
/// Other valid json mime types include: application/json, application/x-json,
/// application/x-javascript, text/javascript, text/x-javascript, text/x-json, text/json
/// </remarks>
public
const
string
ContentTypeJson
=
"application/json"
;
/// <summary>The mime type for query strings and x-www-form-urlencoded content</summary>
/// <remarks>This mime type is input-only</remarks>
public
const
string
ContentFormUrlEncoded
=
"application/x-www-form-urlencoded"
;
/// <summary>
/// Default mime-type handling for input
/// </summary>
private
static
readonly
IDictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>
MimeInputDefaults
=
new
ReadOnlyDictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>(
new
Dictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>(
StringComparer
.
OrdinalIgnoreCase
)
{
{
"application/json"
,
JsonFormatReader
.
CreateInstance
},
{
"application/x-json"
,
JsonFormatReader
.
CreateInstance
},
{
"application/x-javascript"
,
JsonFormatReader
.
CreateInstance
},
{
"text/javascript"
,
JsonFormatReader
.
CreateInstance
},
{
"text/x-javascript"
,
JsonFormatReader
.
CreateInstance
},
{
"text/x-json"
,
JsonFormatReader
.
CreateInstance
},
{
"text/json"
,
JsonFormatReader
.
CreateInstance
},
{
"text/xml"
,
XmlFormatReader
.
CreateInstance
},
{
"application/xml"
,
XmlFormatReader
.
CreateInstance
},
{
"application/binary"
,
CodedInputStream
.
CreateInstance
},
{
"application/x-protobuf"
,
CodedInputStream
.
CreateInstance
},
{
"application/vnd.google.protobuf"
,
CodedInputStream
.
CreateInstance
},
{
"application/x-www-form-urlencoded"
,
FormUrlEncodedReader
.
CreateInstance
},
}
);
/// <summary>
/// Default mime-type handling for output
/// </summary>
private
static
readonly
IDictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>
MimeOutputDefaults
=
new
ReadOnlyDictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>(
new
Dictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>(
StringComparer
.
OrdinalIgnoreCase
)
{
{
"application/json"
,
JsonFormatWriter
.
CreateInstance
},
{
"application/x-json"
,
JsonFormatWriter
.
CreateInstance
},
{
"application/x-javascript"
,
JsonFormatWriter
.
CreateInstance
},
{
"text/javascript"
,
JsonFormatWriter
.
CreateInstance
},
{
"text/x-javascript"
,
JsonFormatWriter
.
CreateInstance
},
{
"text/x-json"
,
JsonFormatWriter
.
CreateInstance
},
{
"text/json"
,
JsonFormatWriter
.
CreateInstance
},
{
"text/xml"
,
XmlFormatWriter
.
CreateInstance
},
{
"application/xml"
,
XmlFormatWriter
.
CreateInstance
},
{
"application/binary"
,
CodedOutputStream
.
CreateInstance
},
{
"application/x-protobuf"
,
CodedOutputStream
.
CreateInstance
},
{
"application/vnd.google.protobuf"
,
CodedOutputStream
.
CreateInstance
},
}
);
private
string
_defaultContentType
;
private
string
_xmlReaderRootElementName
;
private
string
_xmlWriterRootElementName
;
private
ExtensionRegistry
_extensionRegistry
;
private
Dictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>
_mimeInputTypes
;
private
Dictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>
_mimeOutputTypes
;
/// <summary> Provides access to modify the mime-type input stream construction </summary>
public
IDictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>
MimeInputTypes
{
get
{
return
_mimeInputTypes
??
(
_mimeInputTypes
=
new
Dictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>(
MimeInputDefaults
,
StringComparer
.
OrdinalIgnoreCase
));
}
}
/// <summary> Provides access to modify the mime-type input stream construction </summary>
public
IDictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>
MimeOutputTypes
{
get
{
return
_mimeOutputTypes
??
(
_mimeOutputTypes
=
new
Dictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>(
MimeOutputDefaults
,
StringComparer
.
OrdinalIgnoreCase
));
}
}
internal
IDictionary
<
string
,
Converter
<
Stream
,
ICodedInputStream
>>
MimeInputTypesReadOnly
{
get
{
return
_mimeInputTypes
??
MimeInputDefaults
;
}
}
internal
IDictionary
<
string
,
Converter
<
Stream
,
ICodedOutputStream
>>
MimeOutputTypesReadOnly
{
get
{
return
_mimeOutputTypes
??
MimeOutputDefaults
;
}
}
/// <summary>
/// The default content type to use if the input type is null or empty. If this
/// value is not supplied an ArgumentOutOfRangeException exception will be raised.
/// </summary>
public
string
DefaultContentType
{
get
{
return
_defaultContentType
??
String
.
Empty
;
}
set
{
_defaultContentType
=
value
;
}
}
/// <summary>
/// The extension registry to use when reading messages
/// </summary>
public
ExtensionRegistry
ExtensionRegistry
{
get
{
return
_extensionRegistry
??
ExtensionRegistry
.
Empty
;
}
set
{
_extensionRegistry
=
value
;
}
}
/// <summary>
/// The name of the xml root element when reading messages
/// </summary>
public
string
XmlReaderRootElementName
{
get
{
return
_xmlReaderRootElementName
??
XmlFormatReader
.
DefaultRootElementName
;
}
set
{
_xmlReaderRootElementName
=
value
;
}
}
/// <summary>
/// Xml reader options
/// </summary>
public
XmlReaderOptions
XmlReaderOptions
{
get
;
set
;
}
/// <summary>
/// True to use formatted output including new-lines and default indentation
/// </summary>
public
bool
FormattedOutput
{
get
;
set
;
}
/// <summary>
/// The name of the xml root element when writing messages
/// </summary>
public
string
XmlWriterRootElementName
{
get
{
return
_xmlWriterRootElementName
??
XmlFormatWriter
.
DefaultRootElementName
;
}
set
{
_xmlWriterRootElementName
=
value
;
}
}
/// <summary>
/// Xml writer options
/// </summary>
public
XmlWriterOptions
XmlWriterOptions
{
get
;
set
;
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Serialization/Http/ServiceExtensions.cs
0 → 100644
View file @
247c7534
using
System.Collections.Generic
;
using
System.Text
;
using
Google.ProtocolBuffers
;
using
System.IO
;
namespace
Google.ProtocolBuffers.Serialization.Http
{
/// <summary>
/// Extensions for the IRpcServerStub
/// </summary>
public
static
class
ServiceExtensions
{
/// <summary>
/// Used to implement a service endpoint on an HTTP server. This works with services generated with the
/// service_generator_type option set to IRPCDISPATCH.
/// </summary>
/// <param name="stub">The service execution stub</param>
/// <param name="methodName">The name of the method being invoked</param>
/// <param name="options">optional arguments for the format reader/writer</param>
/// <param name="contentType">The mime type for the input stream</param>
/// <param name="input">The input stream</param>
/// <param name="responseType">The mime type for the output stream</param>
/// <param name="output">The output stream</param>
public
static
void
HttpCallMethod
(
this
IRpcServerStub
stub
,
string
methodName
,
MessageFormatOptions
options
,
string
contentType
,
Stream
input
,
string
responseType
,
Stream
output
)
{
ICodedInputStream
codedInput
=
MessageFormatFactory
.
CreateInputStream
(
options
,
contentType
,
input
);
codedInput
.
ReadMessageStart
();
IMessageLite
response
=
stub
.
CallMethod
(
methodName
,
codedInput
,
options
.
ExtensionRegistry
);
codedInput
.
ReadMessageEnd
();
response
.
WriteTo
(
options
,
responseType
,
output
);
}
}
}
src/ProtocolBuffers.Serialization/JsonFormatReader.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Xml
;
using
System.Xml
;
...
@@ -11,6 +11,7 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -11,6 +11,7 @@ namespace Google.ProtocolBuffers.Serialization
public
class
JsonFormatReader
:
AbstractTextReader
public
class
JsonFormatReader
:
AbstractTextReader
{
{
private
readonly
JsonCursor
_input
;
private
readonly
JsonCursor
_input
;
// The expected token that ends the current item, either ']' or '}'
private
readonly
Stack
<
int
>
_stopChar
;
private
readonly
Stack
<
int
>
_stopChar
;
private
enum
ReaderState
private
enum
ReaderState
...
@@ -101,17 +102,33 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -101,17 +102,33 @@ namespace Google.ProtocolBuffers.Serialization
}
}
/// <summary>
/// <summary>
///
Merges the contents of stream into the provided message build
er
///
Reads the root-message preamble specific to this formatt
er
/// </summary>
/// </summary>
public
override
TBuilder
Merge
<
TBuilder
>(
TBuilder
builder
,
ExtensionRegistry
registry
)
public
override
void
ReadMessageStart
(
)
{
{
_input
.
Consume
(
'{'
);
_input
.
Consume
(
'{'
);
_stopChar
.
Push
(
'}'
);
_stopChar
.
Push
(
'}'
);
_state
=
ReaderState
.
BeginObject
;
_state
=
ReaderState
.
BeginObject
;
builder
.
WeakMergeFrom
(
this
,
registry
);
}
_input
.
Consume
((
char
)
_stopChar
.
Pop
());
/// <summary>
/// Reads the root-message close specific to this formatter
/// </summary>
public
override
void
ReadMessageEnd
()
{
_input
.
Consume
((
char
)
_stopChar
.
Pop
());
_state
=
ReaderState
.
EndValue
;
_state
=
ReaderState
.
EndValue
;
}
/// <summary>
/// Merges the contents of stream into the provided message builder
/// </summary>
public
override
TBuilder
Merge
<
TBuilder
>(
TBuilder
builder
,
ExtensionRegistry
registry
)
{
ReadMessageStart
();
builder
.
WeakMergeFrom
(
this
,
registry
);
ReadMessageEnd
();
return
builder
;
return
builder
;
}
}
...
...
src/ProtocolBuffers.Serialization/JsonFormatWriter.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections
;
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
...
@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.Serialization
private
class
JsonStreamWriter
:
JsonFormatWriter
private
class
JsonStreamWriter
:
JsonFormatWriter
{
{
#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
static
readonly
Encoding
Encoding
=
Encoding
.
UTF8
;
static
readonly
Encoding
Encoding
=
new
UTF8Encoding
(
false
)
;
#else
#else
private
static
readonly
Encoding
Encoding
=
Encoding
.
ASCII
;
private
static
readonly
Encoding
Encoding
=
Encoding
.
ASCII
;
#endif
#endif
...
@@ -168,7 +168,9 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -168,7 +168,9 @@ namespace Google.ProtocolBuffers.Serialization
#
endregion
#
endregion
//Tracks the writer depth and the array element count at that depth.
private
readonly
List
<
int
>
_counter
;
private
readonly
List
<
int
>
_counter
;
//True if the top-level of the writer is an array as opposed to a single message.
private
bool
_isArray
;
private
bool
_isArray
;
/// <summary>
/// <summary>
...
@@ -243,7 +245,7 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -243,7 +245,7 @@ namespace Google.ProtocolBuffers.Serialization
{
{
if
(
_counter
.
Count
==
0
)
if
(
_counter
.
Count
==
0
)
{
{
throw
new
InvalidOperationException
(
"Mis
s
matched open/close in Json writer."
);
throw
new
InvalidOperationException
(
"Mismatched open/close in Json writer."
);
}
}
int
index
=
_counter
.
Count
-
1
;
int
index
=
_counter
.
Count
-
1
;
...
@@ -444,6 +446,18 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -444,6 +446,18 @@ namespace Google.ProtocolBuffers.Serialization
/// Writes the message to the the formatted stream.
/// Writes the message to the the formatted stream.
/// </summary>
/// </summary>
public
override
void
WriteMessage
(
IMessageLite
message
)
public
override
void
WriteMessage
(
IMessageLite
message
)
{
WriteMessageStart
();
message
.
WriteTo
(
this
);
WriteMessageEnd
();
}
/// <summary>
/// Used to write the root-message preamble, in json this is the left-curly brace '{'.
/// After this call you can call IMessageLite.MergeTo(...) and complete the message with
/// a call to WriteMessageEnd().
/// </summary>
public
override
void
WriteMessageStart
()
{
{
if
(
_isArray
)
if
(
_isArray
)
{
{
...
@@ -451,7 +465,13 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -451,7 +465,13 @@ namespace Google.ProtocolBuffers.Serialization
}
}
WriteToOutput
(
"{"
);
WriteToOutput
(
"{"
);
_counter
.
Add
(
0
);
_counter
.
Add
(
0
);
message
.
WriteTo
(
this
);
}
/// <summary>
/// Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary>
public
override
void
WriteMessageEnd
()
{
_counter
.
RemoveAt
(
_counter
.
Count
-
1
);
_counter
.
RemoveAt
(
_counter
.
Count
-
1
);
WriteLine
(
"}"
);
WriteLine
(
"}"
);
Flush
();
Flush
();
...
...
src/ProtocolBuffers.Serialization/ProtocolBuffers.Serialization.csproj
View file @
247c7534
...
@@ -98,6 +98,10 @@
...
@@ -98,6 +98,10 @@
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Compile
Include=
"Extensions.cs"
/>
<Compile
Include=
"Extensions.cs"
/>
<Compile
Include=
"Http\FormUrlEncodedReader.cs"
/>
<Compile
Include=
"Http\MessageFormatFactory.cs"
/>
<Compile
Include=
"Http\MessageFormatOptions.cs"
/>
<Compile
Include=
"Http\ServiceExtensions.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"AbstractReader.cs"
/>
<Compile
Include=
"AbstractReader.cs"
/>
<Compile
Include=
"AbstractTextReader.cs"
/>
<Compile
Include=
"AbstractTextReader.cs"
/>
...
...
src/ProtocolBuffers.Serialization/XmlFormatReader.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Xml
;
using
System.Xml
;
using
System.Diagnostics
;
namespace
Google.ProtocolBuffers.Serialization
namespace
Google.ProtocolBuffers.Serialization
{
{
...
@@ -14,8 +15,25 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -14,8 +15,25 @@ namespace Google.ProtocolBuffers.Serialization
{
{
public
const
string
DefaultRootElementName
=
XmlFormatWriter
.
DefaultRootElementName
;
public
const
string
DefaultRootElementName
=
XmlFormatWriter
.
DefaultRootElementName
;
private
readonly
XmlReader
_input
;
private
readonly
XmlReader
_input
;
// Tracks the message element for each nested message read
private
readonly
Stack
<
ElementStackEntry
>
_elements
;
// The default element name for ReadMessageStart
private
string
_rootElementName
;
private
string
_rootElementName
;
private
struct
ElementStackEntry
{
public
readonly
string
LocalName
;
public
readonly
int
Depth
;
public
readonly
bool
IsEmpty
;
public
ElementStackEntry
(
string
localName
,
int
depth
,
bool
isEmpty
)
:
this
()
{
LocalName
=
localName
;
IsEmpty
=
isEmpty
;
Depth
=
depth
;
}
}
private
static
XmlReaderSettings
DefaultSettings
private
static
XmlReaderSettings
DefaultSettings
{
{
get
get
...
@@ -72,20 +90,10 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -72,20 +90,10 @@ namespace Google.ProtocolBuffers.Serialization
{
{
_input
=
input
;
_input
=
input
;
_rootElementName
=
DefaultRootElementName
;
_rootElementName
=
DefaultRootElementName
;
_elements
=
new
Stack
<
ElementStackEntry
>();
Options
=
XmlReaderOptions
.
None
;
Options
=
XmlReaderOptions
.
None
;
}
}
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader and options
/// </summary>
protected
XmlFormatReader
(
XmlFormatReader
copyFrom
,
XmlReader
input
)
:
base
(
copyFrom
)
{
_input
=
input
;
_rootElementName
=
copyFrom
.
_rootElementName
;
Options
=
copyFrom
.
Options
;
}
/// <summary>
/// <summary>
/// Gets or sets the options to use when reading the xml
/// Gets or sets the options to use when reading the xml
/// </summary>
/// </summary>
...
@@ -113,26 +121,61 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -113,26 +121,61 @@ namespace Google.ProtocolBuffers.Serialization
}
}
}
}
private
XmlFormatReader
CloneWith
(
XmlReader
rdr
)
[
DebuggerNonUserCode
]
private
static
void
Assert
(
bool
cond
)
{
{
XmlFormatReader
copy
=
new
XmlFormatReader
(
this
,
rdr
);
if
(!
cond
)
return
copy
;
{
throw
new
FormatException
();
}
}
}
private
void
NextElement
()
/// <summary>
/// Reads the root-message preamble specific to this formatter
/// </summary>
public
override
void
ReadMessageStart
()
{
ReadMessageStart
(
_rootElementName
);
}
/// <summary>
/// Reads the root-message preamble specific to this formatter
/// </summary>
public
void
ReadMessageStart
(
string
element
)
{
{
while
(!
_input
.
IsStartElement
()
&&
_input
.
Read
())
while
(!
_input
.
IsStartElement
()
&&
_input
.
Read
())
{
{
continue
;
continue
;
}
}
Assert
(
_input
.
IsStartElement
()
&&
_input
.
LocalName
==
element
);
_elements
.
Push
(
new
ElementStackEntry
(
element
,
_input
.
Depth
,
_input
.
IsEmptyElement
));
_input
.
Read
();
}
}
private
static
void
Assert
(
bool
cond
)
/// <summary>
/// Reads the root-message close specific to this formatter, MUST be called
/// on the reader obtained from ReadMessageStart(string element).
/// </summary>
public
override
void
ReadMessageEnd
()
{
{
if
(!
cond
)
Assert
(
_elements
.
Count
>
0
);
ElementStackEntry
stop
=
_elements
.
Peek
();
while
(
_input
.
NodeType
!=
XmlNodeType
.
EndElement
&&
_input
.
NodeType
!=
XmlNodeType
.
Element
&&
_input
.
Depth
>
stop
.
Depth
&&
_input
.
Read
())
{
{
throw
new
FormatException
();
continue
;
}
if
(!
stop
.
IsEmpty
)
{
Assert
(
_input
.
NodeType
==
XmlNodeType
.
EndElement
&&
_input
.
LocalName
==
stop
.
LocalName
&&
_input
.
Depth
==
stop
.
Depth
);
_input
.
Read
();
}
}
_elements
.
Pop
();
}
}
/// <summary>
/// <summary>
...
@@ -157,9 +200,9 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -157,9 +200,9 @@ namespace Google.ProtocolBuffers.Serialization
public
TBuilder
Merge
<
TBuilder
>(
string
element
,
TBuilder
builder
,
ExtensionRegistry
registry
)
public
TBuilder
Merge
<
TBuilder
>(
string
element
,
TBuilder
builder
,
ExtensionRegistry
registry
)
where
TBuilder
:
IBuilderLite
where
TBuilder
:
IBuilderLite
{
{
string
field
;
ReadMessageStart
(
element
)
;
Assert
(
PeekNext
(
out
field
)
&&
field
==
element
);
builder
.
WeakMergeFrom
(
this
,
registry
);
ReadMessage
(
builder
,
registry
);
ReadMessage
End
(
);
return
builder
;
return
builder
;
}
}
...
@@ -172,7 +215,21 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -172,7 +215,21 @@ namespace Google.ProtocolBuffers.Serialization
/// </remarks>
/// </remarks>
protected
override
bool
PeekNext
(
out
string
field
)
protected
override
bool
PeekNext
(
out
string
field
)
{
{
NextElement
();
ElementStackEntry
stopNode
;
if
(
_elements
.
Count
==
0
)
{
stopNode
=
new
ElementStackEntry
(
null
,
_input
.
Depth
-
1
,
false
);
}
else
{
stopNode
=
_elements
.
Peek
();
}
while
(!
_input
.
IsStartElement
()
&&
_input
.
Depth
>
stopNode
.
Depth
&&
_input
.
Read
())
{
continue
;
}
if
(
_input
.
IsStartElement
())
if
(
_input
.
IsStartElement
())
{
{
field
=
_input
.
LocalName
;
field
=
_input
.
LocalName
;
...
@@ -235,20 +292,9 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -235,20 +292,9 @@ namespace Google.ProtocolBuffers.Serialization
protected
override
bool
ReadMessage
(
IBuilderLite
builder
,
ExtensionRegistry
registry
)
protected
override
bool
ReadMessage
(
IBuilderLite
builder
,
ExtensionRegistry
registry
)
{
{
Assert
(
_input
.
IsStartElement
());
Assert
(
_input
.
IsStartElement
());
ReadMessageStart
(
_input
.
LocalName
);
if
(!
_input
.
IsEmptyElement
)
builder
.
WeakMergeFrom
(
this
,
registry
);
{
ReadMessageEnd
();
int
depth
=
_input
.
Depth
;
XmlReader
child
=
_input
.
ReadSubtree
();
while
(!
child
.
IsStartElement
()
&&
child
.
Read
())
{
continue
;
}
child
.
Read
();
builder
.
WeakMergeFrom
(
CloneWith
(
child
),
registry
);
Assert
(
depth
==
_input
.
Depth
&&
_input
.
NodeType
==
XmlNodeType
.
EndElement
);
}
_input
.
Read
();
return
true
;
return
true
;
}
}
...
@@ -270,27 +316,20 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -270,27 +316,20 @@ namespace Google.ProtocolBuffers.Serialization
{
{
yield
return
item
;
yield
return
item
;
}
}
yield
break
;
}
}
if
(!
_input
.
IsEmptyElement
)
else
{
{
int
depth
=
_input
.
Depth
;
string
found
;
XmlReader
child
=
_input
.
ReadSubtree
();
ReadMessageStart
(
field
);
if
(
PeekNext
(
out
found
)
&&
found
==
"item"
)
while
(!
child
.
IsStartElement
()
&&
child
.
Read
())
{
{
continue
;
foreach
(
string
item
in
NonNestedArrayItems
(
"item"
))
}
{
child
.
Read
();
yield
return
item
;
}
foreach
(
string
item
in
CloneWith
(
child
).
NonNestedArrayItems
(
"item"
))
{
yield
return
item
;
}
}
Assert
(
depth
==
_input
.
Depth
&&
_input
.
NodeType
==
XmlNodeType
.
EndElement
);
ReadMessageEnd
(
);
}
}
_input
.
Read
();
yield
break
;
}
}
}
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Serialization/XmlFormatWriter.cs
View file @
247c7534
using
System
;
using
System
;
using
System.Collections
;
using
System.Collections
;
using
System.IO
;
using
System.IO
;
using
System.Text
;
using
System.Text
;
...
@@ -14,10 +14,14 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -14,10 +14,14 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary>
/// </summary>
public
class
XmlFormatWriter
:
AbstractTextWriter
public
class
XmlFormatWriter
:
AbstractTextWriter
{
{
private
static
readonly
Encoding
DefaultEncoding
=
new
UTF8Encoding
(
false
);
public
const
string
DefaultRootElementName
=
"root"
;
public
const
string
DefaultRootElementName
=
"root"
;
private
const
int
NestedArrayFlag
=
0x0001
;
private
readonly
XmlWriter
_output
;
private
readonly
XmlWriter
_output
;
// The default element name used for WriteMessageStart
private
string
_rootElementName
;
private
string
_rootElementName
;
// Used to assert matching WriteMessageStart/WriteMessageEnd calls
private
int
_messageOpenCount
;
private
static
XmlWriterSettings
DefaultSettings
(
Encoding
encoding
)
private
static
XmlWriterSettings
DefaultSettings
(
Encoding
encoding
)
{
{
...
@@ -43,7 +47,7 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -43,7 +47,7 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary>
/// </summary>
public
static
XmlFormatWriter
CreateInstance
(
Stream
output
)
public
static
XmlFormatWriter
CreateInstance
(
Stream
output
)
{
{
return
new
XmlFormatWriter
(
XmlWriter
.
Create
(
output
,
DefaultSettings
(
Encoding
.
UTF8
)));
return
new
XmlFormatWriter
(
XmlWriter
.
Create
(
output
,
DefaultSettings
(
DefaultEncoding
)));
}
}
/// <summary>
/// <summary>
...
@@ -65,20 +69,10 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -65,20 +69,10 @@ namespace Google.ProtocolBuffers.Serialization
protected
XmlFormatWriter
(
XmlWriter
output
)
protected
XmlFormatWriter
(
XmlWriter
output
)
{
{
_output
=
output
;
_output
=
output
;
_messageOpenCount
=
0
;
_rootElementName
=
DefaultRootElementName
;
_rootElementName
=
DefaultRootElementName
;
}
}
/// <summary>
/// Closes the underlying XmlTextWriter
/// </summary>
protected
override
void
Dispose
(
bool
disposing
)
{
if
(
disposing
)
{
_output
.
Close
();
}
}
/// <summary>
/// <summary>
/// Gets or sets the default element name to use when using the Merge<TBuilder>()
/// Gets or sets the default element name to use when using the Merge<TBuilder>()
/// </summary>
/// </summary>
...
@@ -112,17 +106,30 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -112,17 +106,30 @@ namespace Google.ProtocolBuffers.Serialization
}
}
/// <summary>
/// <summary>
///
Writes a message as an element using the name defined in <see cref="RootElementName"/>
///
Completes any pending write operations
/// </summary>
/// </summary>
public
override
void
WriteMessage
(
IMessageLite
message
)
public
override
void
Flush
(
)
{
{
WriteMessage
(
_rootElementName
,
message
);
_output
.
Flush
();
base
.
Flush
();
}
}
/// <summary>
/// <summary>
/// Writes a message as an element with the given name
/// Used to write the root-message preamble, in xml this is open element for RootElementName,
/// by default "<root>". After this call you can call IMessageLite.MergeTo(...) and
/// complete the message with a call to WriteMessageEnd().
/// </summary>
/// </summary>
public
void
WriteMessage
(
string
elementName
,
IMessageLite
message
)
public
override
void
WriteMessageStart
()
{
WriteMessageStart
(
_rootElementName
);
}
/// <summary>
/// Used to write the root-message preamble, in xml this is open element for elementName.
/// After this call you can call IMessageLite.MergeTo(...) and complete the message with
/// a call to WriteMessageEnd().
/// </summary>
public
void
WriteMessageStart
(
string
elementName
)
{
{
if
(
TestOption
(
XmlWriterOptions
.
OutputJsonTypes
))
if
(
TestOption
(
XmlWriterOptions
.
OutputJsonTypes
))
{
{
...
@@ -133,10 +140,40 @@ namespace Google.ProtocolBuffers.Serialization
...
@@ -133,10 +140,40 @@ namespace Google.ProtocolBuffers.Serialization
{
{
_output
.
WriteStartElement
(
elementName
);
_output
.
WriteStartElement
(
elementName
);
}
}
_messageOpenCount
++;
}
/// <summary>
/// Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary>
public
override
void
WriteMessageEnd
()
{
if
(
_messageOpenCount
<=
0
)
{
throw
new
InvalidOperationException
();
}
message
.
WriteTo
(
this
);
_output
.
WriteEndElement
();
_output
.
WriteEndElement
();
_output
.
Flush
();
_output
.
Flush
();
_messageOpenCount
--;
}
/// <summary>
/// Writes a message as an element using the name defined in <see cref="RootElementName"/>
/// </summary>
public
override
void
WriteMessage
(
IMessageLite
message
)
{
WriteMessage
(
_rootElementName
,
message
);
}
/// <summary>
/// Writes a message as an element with the given name
/// </summary>
public
void
WriteMessage
(
string
elementName
,
IMessageLite
message
)
{
WriteMessageStart
(
elementName
);
message
.
WriteTo
(
this
);
WriteMessageEnd
();
}
}
/// <summary>
/// <summary>
...
...
src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs
View file @
247c7534
...
@@ -7,6 +7,24 @@ namespace Google.ProtocolBuffers.Compatibility
...
@@ -7,6 +7,24 @@ namespace Google.ProtocolBuffers.Compatibility
{
{
[
TestFixture
]
[
TestFixture
]
public
class
JsonCompatibilityTests
:
CompatibilityTests
public
class
JsonCompatibilityTests
:
CompatibilityTests
{
protected
override
object
SerializeMessage
<
TMessage
,
TBuilder
>(
TMessage
message
)
{
StringWriter
sw
=
new
StringWriter
();
JsonFormatWriter
.
CreateInstance
(
sw
)
.
WriteMessage
(
message
);
return
sw
.
ToString
();
}
protected
override
TBuilder
DeserializeMessage
<
TMessage
,
TBuilder
>(
object
message
,
TBuilder
builder
,
ExtensionRegistry
registry
)
{
JsonFormatReader
.
CreateInstance
((
string
)
message
).
Merge
(
builder
);
return
builder
;
}
}
[
TestFixture
]
public
class
JsonCompatibilityFormattedTests
:
CompatibilityTests
{
{
protected
override
object
SerializeMessage
<
TMessage
,
TBuilder
>(
TMessage
message
)
protected
override
object
SerializeMessage
<
TMessage
,
TBuilder
>(
TMessage
message
)
{
{
...
...
src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs
View file @
247c7534
using
System.IO
;
using
System.IO
;
using
System.Xml
;
using
Google.ProtocolBuffers.Serialization
;
using
Google.ProtocolBuffers.Serialization
;
using
Google.ProtocolBuffers.TestProtos
;
using
Google.ProtocolBuffers.TestProtos
;
using
NUnit.Framework
;
using
NUnit.Framework
;
...
@@ -22,4 +23,24 @@ namespace Google.ProtocolBuffers.Compatibility
...
@@ -22,4 +23,24 @@ namespace Google.ProtocolBuffers.Compatibility
return
reader
.
Merge
(
"root"
,
builder
,
registry
);
return
reader
.
Merge
(
"root"
,
builder
,
registry
);
}
}
}
}
[
TestFixture
]
public
class
XmlCompatibilityFormattedTests
:
CompatibilityTests
{
protected
override
object
SerializeMessage
<
TMessage
,
TBuilder
>(
TMessage
message
)
{
StringWriter
text
=
new
StringWriter
();
XmlWriter
xwtr
=
XmlWriter
.
Create
(
text
,
new
XmlWriterSettings
{
Indent
=
true
,
IndentChars
=
" "
});
XmlFormatWriter
writer
=
XmlFormatWriter
.
CreateInstance
(
xwtr
).
SetOptions
(
XmlWriterOptions
.
OutputNestedArrays
);
writer
.
WriteMessage
(
"root"
,
message
);
return
text
.
ToString
();
}
protected
override
TBuilder
DeserializeMessage
<
TMessage
,
TBuilder
>(
object
message
,
TBuilder
builder
,
ExtensionRegistry
registry
)
{
XmlFormatReader
reader
=
XmlFormatReader
.
CreateInstance
((
string
)
message
).
SetOptions
(
XmlReaderOptions
.
ReadNestedArrays
);
return
reader
.
Merge
(
"root"
,
builder
,
registry
);
}
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
View file @
247c7534
...
@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
...
@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProtocolBuffers.Test")]
[assembly: AssemblyProduct("ProtocolBuffers.Test")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyCopyright("Copyright
�
2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyCulture("")]
...
...
src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
View file @
247c7534
...
@@ -88,6 +88,8 @@
...
@@ -88,6 +88,8 @@
</Compile>
</Compile>
<Compile
Include=
"Compatibility\TextCompatibilityTests.cs"
/>
<Compile
Include=
"Compatibility\TextCompatibilityTests.cs"
/>
<Compile
Include=
"Compatibility\XmlCompatibilityTests.cs"
/>
<Compile
Include=
"Compatibility\XmlCompatibilityTests.cs"
/>
<Compile
Include=
"TestRpcForMimeTypes.cs"
/>
<Compile
Include=
"TestReaderForUrlEncoded.cs"
/>
<Compile
Include=
"CSharpOptionsTest.cs"
/>
<Compile
Include=
"CSharpOptionsTest.cs"
/>
<Compile
Include=
"DeprecatedMemberTest.cs"
/>
<Compile
Include=
"DeprecatedMemberTest.cs"
/>
<Compile
Include=
"DescriptorsTest.cs"
/>
<Compile
Include=
"DescriptorsTest.cs"
/>
...
@@ -107,6 +109,7 @@
...
@@ -107,6 +109,7 @@
<Compile
Include=
"SerializableTest.cs"
/>
<Compile
Include=
"SerializableTest.cs"
/>
<Compile
Include=
"ServiceTest.cs"
/>
<Compile
Include=
"ServiceTest.cs"
/>
<Compile
Include=
"TestCornerCases.cs"
/>
<Compile
Include=
"TestCornerCases.cs"
/>
<Compile
Include=
"TestMimeMessageFormats.cs"
/>
<Compile
Include=
"TestProtos\UnitTestCSharpOptionsProtoFile.cs"
/>
<Compile
Include=
"TestProtos\UnitTestCSharpOptionsProtoFile.cs"
/>
<Compile
Include=
"TestProtos\UnitTestCustomOptionsProtoFile.cs"
/>
<Compile
Include=
"TestProtos\UnitTestCustomOptionsProtoFile.cs"
/>
<Compile
Include=
"TestProtos\UnitTestEmbedOptimizeForProtoFile.cs"
/>
<Compile
Include=
"TestProtos\UnitTestEmbedOptimizeForProtoFile.cs"
/>
...
...
src/ProtocolBuffers.Test/TestMimeMessageFormats.cs
0 → 100644
View file @
247c7534
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Text
;
using
Google.ProtocolBuffers.Serialization
;
using
Google.ProtocolBuffers.Serialization.Http
;
using
Google.ProtocolBuffers.TestProtos
;
using
NUnit.Framework
;
namespace
Google.ProtocolBuffers
{
[
TestFixture
]
public
class
TestMimeMessageFormats
{
// There is a whole host of various json mime types in use around the net, this is the set we accept...
readonly
IEnumerable
<
string
>
JsonTypes
=
new
string
[]
{
"application/json"
,
"application/x-json"
,
"application/x-javascript"
,
"text/javascript"
,
"text/x-javascript"
,
"text/x-json"
,
"text/json"
};
readonly
IEnumerable
<
string
>
XmlTypes
=
new
string
[]
{
"text/xml"
,
"application/xml"
};
readonly
IEnumerable
<
string
>
ProtobufTypes
=
new
string
[]
{
"application/binary"
,
"application/x-protobuf"
,
"application/vnd.google.protobuf"
};
[
Test
]
public
void
TestReadJsonMimeTypes
()
{
foreach
(
string
type
in
JsonTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
JsonFormatReader
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/json"
},
null
,
Stream
.
Null
)
is
JsonFormatReader
);
}
[
Test
]
public
void
TestWriteJsonMimeTypes
()
{
foreach
(
string
type
in
JsonTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
JsonFormatWriter
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/json"
},
null
,
Stream
.
Null
)
is
JsonFormatWriter
);
}
[
Test
]
public
void
TestReadXmlMimeTypes
()
{
foreach
(
string
type
in
XmlTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
XmlFormatReader
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/xml"
},
null
,
Stream
.
Null
)
is
XmlFormatReader
);
}
[
Test
]
public
void
TestWriteXmlMimeTypes
()
{
foreach
(
string
type
in
XmlTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
XmlFormatWriter
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/xml"
},
null
,
Stream
.
Null
)
is
XmlFormatWriter
);
}
[
Test
]
public
void
TestReadProtoMimeTypes
()
{
foreach
(
string
type
in
ProtobufTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
CodedInputStream
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateInputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/vnd.google.protobuf"
},
null
,
Stream
.
Null
)
is
CodedInputStream
);
}
[
Test
]
public
void
TestWriteProtoMimeTypes
()
{
foreach
(
string
type
in
ProtobufTypes
)
{
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
(),
type
,
Stream
.
Null
)
is
CodedOutputStream
);
}
Assert
.
IsTrue
(
MessageFormatFactory
.
CreateOutputStream
(
new
MessageFormatOptions
()
{
DefaultContentType
=
"application/vnd.google.protobuf"
},
null
,
Stream
.
Null
)
is
CodedOutputStream
);
}
[
Test
]
public
void
TestMergeFromJsonType
()
{
TestXmlMessage
msg
=
new
TestXmlMessage
.
Builder
().
MergeFrom
(
new
MessageFormatOptions
(),
"application/json"
,
new
MemoryStream
(
Encoding
.
ASCII
.
GetBytes
(
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
().
ToJson
()
)))
.
Build
();
Assert
.
AreEqual
(
"a"
,
msg
.
Text
);
Assert
.
AreEqual
(
1
,
msg
.
Number
);
}
[
Test
]
public
void
TestMergeFromXmlType
()
{
TestXmlMessage
msg
=
new
TestXmlMessage
.
Builder
().
MergeFrom
(
new
MessageFormatOptions
(),
"application/xml"
,
new
MemoryStream
(
Encoding
.
ASCII
.
GetBytes
(
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
().
ToXml
()
)))
.
Build
();
Assert
.
AreEqual
(
"a"
,
msg
.
Text
);
Assert
.
AreEqual
(
1
,
msg
.
Number
);
}
[
Test
]
public
void
TestMergeFromProtoType
()
{
TestXmlMessage
msg
=
new
TestXmlMessage
.
Builder
().
MergeFrom
(
new
MessageFormatOptions
(),
"application/vnd.google.protobuf"
,
new
MemoryStream
(
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
().
ToByteArray
()
))
.
Build
();
Assert
.
AreEqual
(
"a"
,
msg
.
Text
);
Assert
.
AreEqual
(
1
,
msg
.
Number
);
}
[
Test
]
public
void
TestWriteToJsonType
()
{
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
new
MessageFormatOptions
(),
"application/json"
,
ms
);
Assert
.
AreEqual
(
@"{""text"":""a"",""number"":1}"
,
Encoding
.
UTF8
.
GetString
(
ms
.
ToArray
()));
}
[
Test
]
public
void
TestWriteToXmlType
()
{
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
new
MessageFormatOptions
(),
"application/xml"
,
ms
);
Assert
.
AreEqual
(
"<root><text>a</text><number>1</number></root>"
,
Encoding
.
UTF8
.
GetString
(
ms
.
ToArray
()));
}
[
Test
]
public
void
TestWriteToProtoType
()
{
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
new
MessageFormatOptions
(),
"application/vnd.google.protobuf"
,
ms
);
byte
[]
bytes
=
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
().
ToByteArray
();
Assert
.
AreEqual
(
bytes
,
ms
.
ToArray
());
}
[
Test
]
public
void
TestXmlReaderOptions
()
{
MemoryStream
ms
=
new
MemoryStream
();
XmlFormatWriter
.
CreateInstance
(
ms
)
.
SetOptions
(
XmlWriterOptions
.
OutputNestedArrays
)
.
WriteMessage
(
"my-root-node"
,
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
AddNumbers
(
1
).
AddNumbers
(
2
).
Build
());
ms
.
Position
=
0
;
MessageFormatOptions
options
=
new
MessageFormatOptions
()
{
XmlReaderOptions
=
XmlReaderOptions
.
ReadNestedArrays
,
XmlReaderRootElementName
=
"my-root-node"
};
TestXmlMessage
msg
=
new
TestXmlMessage
.
Builder
().
MergeFrom
(
options
,
"application/xml"
,
ms
)
.
Build
();
Assert
.
AreEqual
(
"a"
,
msg
.
Text
);
Assert
.
AreEqual
(
1
,
msg
.
NumbersList
[
0
]);
Assert
.
AreEqual
(
2
,
msg
.
NumbersList
[
1
]);
}
[
Test
]
public
void
TestXmlWriterOptions
()
{
TestXmlMessage
message
=
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
AddNumbers
(
1
).
AddNumbers
(
2
).
Build
();
MessageFormatOptions
options
=
new
MessageFormatOptions
()
{
XmlWriterOptions
=
XmlWriterOptions
.
OutputNestedArrays
,
XmlWriterRootElementName
=
"root-node"
};
MemoryStream
ms
=
new
MemoryStream
();
message
.
WriteTo
(
options
,
"application/xml"
,
ms
);
ms
.
Position
=
0
;
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
XmlFormatReader
.
CreateInstance
(
ms
)
.
SetOptions
(
XmlReaderOptions
.
ReadNestedArrays
)
.
Merge
(
"root-node"
,
builder
);
Assert
.
AreEqual
(
"a"
,
builder
.
Text
);
Assert
.
AreEqual
(
1
,
builder
.
NumbersList
[
0
]);
Assert
.
AreEqual
(
2
,
builder
.
NumbersList
[
1
]);
}
[
Test
]
public
void
TestJsonFormatted
()
{
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
new
MessageFormatOptions
()
{
FormattedOutput
=
true
},
"application/json"
,
ms
);
Assert
.
AreEqual
(
"{\r\n \"text\": \"a\",\r\n \"number\": 1\r\n}"
,
Encoding
.
UTF8
.
GetString
(
ms
.
ToArray
()));
}
[
Test
]
public
void
TestXmlFormatted
()
{
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
new
MessageFormatOptions
()
{
FormattedOutput
=
true
},
"application/xml"
,
ms
);
Assert
.
AreEqual
(
"<root>\r\n <text>a</text>\r\n <number>1</number>\r\n</root>"
,
Encoding
.
UTF8
.
GetString
(
ms
.
ToArray
()));
}
[
Test
]
public
void
TestReadCustomMimeTypes
()
{
var
options
=
new
MessageFormatOptions
();
//Remove existing mime-type mappings
options
.
MimeInputTypes
.
Clear
();
//Add our own
options
.
MimeInputTypes
.
Add
(
"-custom-XML-mime-type-"
,
XmlFormatReader
.
CreateInstance
);
Assert
.
AreEqual
(
1
,
options
.
MimeInputTypes
.
Count
);
Stream
xmlStream
=
new
MemoryStream
(
Encoding
.
ASCII
.
GetBytes
(
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
().
ToXml
()
));
TestXmlMessage
msg
=
new
TestXmlMessage
.
Builder
().
MergeFrom
(
options
,
"-custom-XML-mime-type-"
,
xmlStream
)
.
Build
();
Assert
.
AreEqual
(
"a"
,
msg
.
Text
);
Assert
.
AreEqual
(
1
,
msg
.
Number
);
}
[
Test
]
public
void
TestWriteToCustomType
()
{
var
options
=
new
MessageFormatOptions
();
//Remove existing mime-type mappings
options
.
MimeOutputTypes
.
Clear
();
//Add our own
options
.
MimeOutputTypes
.
Add
(
"-custom-XML-mime-type-"
,
XmlFormatWriter
.
CreateInstance
);
Assert
.
AreEqual
(
1
,
options
.
MimeOutputTypes
.
Count
);
MemoryStream
ms
=
new
MemoryStream
();
TestXmlMessage
.
CreateBuilder
().
SetText
(
"a"
).
SetNumber
(
1
).
Build
()
.
WriteTo
(
options
,
"-custom-XML-mime-type-"
,
ms
);
Assert
.
AreEqual
(
"<root><text>a</text><number>1</number></root>"
,
Encoding
.
UTF8
.
GetString
(
ms
.
ToArray
()));
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs
0 → 100644
View file @
247c7534
using
System
;
using
System.IO
;
using
System.Text
;
using
NUnit.Framework
;
using
Google.ProtocolBuffers.TestProtos
;
using
Google.ProtocolBuffers.Serialization.Http
;
namespace
Google.ProtocolBuffers
{
[
TestFixture
]
public
class
TestReaderForUrlEncoded
{
[
Test
]
public
void
Example_FromQueryString
()
{
Uri
sampleUri
=
new
Uri
(
"http://sample.com/Path/File.ext?text=two+three%20four&valid=true&numbers=1&numbers=2"
,
UriKind
.
Absolute
);
ICodedInputStream
input
=
FormUrlEncodedReader
.
CreateInstance
(
sampleUri
.
Query
);
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
builder
.
MergeFrom
(
input
);
TestXmlMessage
message
=
builder
.
Build
();
Assert
.
AreEqual
(
true
,
message
.
Valid
);
Assert
.
AreEqual
(
"two three four"
,
message
.
Text
);
Assert
.
AreEqual
(
2
,
message
.
NumbersCount
);
Assert
.
AreEqual
(
1
,
message
.
NumbersList
[
0
]);
Assert
.
AreEqual
(
2
,
message
.
NumbersList
[
1
]);
}
[
Test
]
public
void
Example_FromFormData
()
{
Stream
rawPost
=
new
MemoryStream
(
Encoding
.
UTF8
.
GetBytes
(
"text=two+three%20four&valid=true&numbers=1&numbers=2"
),
false
);
ICodedInputStream
input
=
FormUrlEncodedReader
.
CreateInstance
(
rawPost
);
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
builder
.
MergeFrom
(
input
);
TestXmlMessage
message
=
builder
.
Build
();
Assert
.
AreEqual
(
true
,
message
.
Valid
);
Assert
.
AreEqual
(
"two three four"
,
message
.
Text
);
Assert
.
AreEqual
(
2
,
message
.
NumbersCount
);
Assert
.
AreEqual
(
1
,
message
.
NumbersList
[
0
]);
Assert
.
AreEqual
(
2
,
message
.
NumbersList
[
1
]);
}
[
Test
]
public
void
TestEmptyValues
()
{
ICodedInputStream
input
=
FormUrlEncodedReader
.
CreateInstance
(
"valid=true&text=&numbers=1"
);
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
builder
.
MergeFrom
(
input
);
Assert
.
IsTrue
(
builder
.
Valid
);
Assert
.
IsTrue
(
builder
.
HasText
);
Assert
.
AreEqual
(
""
,
builder
.
Text
);
Assert
.
AreEqual
(
1
,
builder
.
NumbersCount
);
Assert
.
AreEqual
(
1
,
builder
.
NumbersList
[
0
]);
}
[
Test
]
public
void
TestNoValue
()
{
ICodedInputStream
input
=
FormUrlEncodedReader
.
CreateInstance
(
"valid=true&text&numbers=1"
);
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
builder
.
MergeFrom
(
input
);
Assert
.
IsTrue
(
builder
.
Valid
);
Assert
.
IsTrue
(
builder
.
HasText
);
Assert
.
AreEqual
(
""
,
builder
.
Text
);
Assert
.
AreEqual
(
1
,
builder
.
NumbersCount
);
Assert
.
AreEqual
(
1
,
builder
.
NumbersList
[
0
]);
}
[
Test
,
ExpectedException
(
typeof
(
NotSupportedException
))]
public
void
FormUrlEncodedReaderDoesNotSupportChildren
()
{
ICodedInputStream
input
=
FormUrlEncodedReader
.
CreateInstance
(
"child=uh0"
);
TestXmlMessage
.
CreateBuilder
().
MergeFrom
(
input
);
}
}
}
src/ProtocolBuffers.Test/TestRpcForMimeTypes.cs
0 → 100644
View file @
247c7534
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://github.com/jskeet/dotnet-protobufs/
// Original C++/Java/Python code:
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using
System
;
using
Google.ProtocolBuffers
;
using
Google.ProtocolBuffers.Serialization.Http
;
using
Google.ProtocolBuffers.TestProtos
;
using
NUnit.Framework
;
using
System.IO
;
using
Google.ProtocolBuffers.Serialization
;
using
System.Text
;
namespace
Google.ProtocolBuffers
{
/// <summary>
/// This class verifies the correct code is generated from unittest_rpc_interop.proto and provides a small demonstration
/// of using the new IRpcDispatch to write a client/server
/// </summary>
[
TestFixture
]
public
class
TestRpcForMimeTypes
{
/// <summary>
/// A sample implementation of the ISearchService for testing
/// </summary>
private
class
ExampleSearchImpl
:
ISearchService
{
SearchResponse
ISearchService
.
Search
(
SearchRequest
searchRequest
)
{
if
(
searchRequest
.
CriteriaCount
==
0
)
{
throw
new
ArgumentException
(
"No criteria specified."
,
new
InvalidOperationException
());
}
SearchResponse
.
Builder
resp
=
SearchResponse
.
CreateBuilder
();
foreach
(
string
criteria
in
searchRequest
.
CriteriaList
)
{
resp
.
AddResults
(
SearchResponse
.
Types
.
ResultItem
.
CreateBuilder
().
SetName
(
criteria
).
SetUrl
(
"http://search.com"
).
Build
());
}
return
resp
.
Build
();
}
SearchResponse
ISearchService
.
RefineSearch
(
RefineSearchRequest
refineSearchRequest
)
{
SearchResponse
.
Builder
resp
=
refineSearchRequest
.
PreviousResults
.
ToBuilder
();
foreach
(
string
criteria
in
refineSearchRequest
.
CriteriaList
)
{
resp
.
AddResults
(
SearchResponse
.
Types
.
ResultItem
.
CreateBuilder
().
SetName
(
criteria
).
SetUrl
(
"http://refine.com"
).
Build
());
}
return
resp
.
Build
();
}
}
/// <summary>
/// An example extraction of the wire protocol
/// </summary>
private
interface
IHttpTransfer
{
void
Execute
(
string
method
,
string
contentType
,
Stream
input
,
string
acceptType
,
Stream
output
);
}
/// <summary>
/// An example of a server responding to a web/http request
/// </summary>
private
class
ExampleHttpServer
:
IHttpTransfer
{
public
readonly
MessageFormatOptions
Options
=
new
MessageFormatOptions
{
ExtensionRegistry
=
ExtensionRegistry
.
Empty
,
FormattedOutput
=
true
,
XmlReaderOptions
=
XmlReaderOptions
.
ReadNestedArrays
,
XmlReaderRootElementName
=
"request"
,
XmlWriterOptions
=
XmlWriterOptions
.
OutputNestedArrays
,
XmlWriterRootElementName
=
"response"
};
private
readonly
IRpcServerStub
_stub
;
public
ExampleHttpServer
(
ISearchService
implementation
)
{
//on the server, we create a dispatch to call the appropriate method by name
IRpcDispatch
dispatch
=
new
SearchService
.
Dispatch
(
implementation
);
//we then wrap that dispatch in a server stub which will deserialize the wire bytes to the message
//type appropriate for the method name being invoked.
_stub
=
new
SearchService
.
ServerStub
(
dispatch
);
}
void
IHttpTransfer
.
Execute
(
string
method
,
string
contentType
,
Stream
input
,
string
acceptType
,
Stream
output
)
{
//Extension for: Google.ProtocolBuffers.Serialization.Http.ServiceExtensions.HttpCallMethod(_stub,
_stub
.
HttpCallMethod
(
method
,
Options
,
contentType
,
input
,
acceptType
,
output
);
}
}
/// <summary>
/// An example of a client sending a wire request
/// </summary>
private
class
ExampleClient
:
IRpcDispatch
{
public
readonly
MessageFormatOptions
Options
=
new
MessageFormatOptions
{
ExtensionRegistry
=
ExtensionRegistry
.
Empty
,
FormattedOutput
=
true
,
XmlReaderOptions
=
XmlReaderOptions
.
ReadNestedArrays
,
XmlReaderRootElementName
=
"response"
,
XmlWriterOptions
=
XmlWriterOptions
.
OutputNestedArrays
,
XmlWriterRootElementName
=
"request"
};
private
readonly
IHttpTransfer
_wire
;
private
readonly
string
_mimeType
;
public
ExampleClient
(
IHttpTransfer
wire
,
string
mimeType
)
{
_wire
=
wire
;
_mimeType
=
mimeType
;
}
TMessage
IRpcDispatch
.
CallMethod
<
TMessage
,
TBuilder
>(
string
method
,
IMessageLite
request
,
IBuilderLite
<
TMessage
,
TBuilder
>
response
)
{
MemoryStream
input
=
new
MemoryStream
();
MemoryStream
output
=
new
MemoryStream
();
//Write to _mimeType format
request
.
WriteTo
(
Options
,
_mimeType
,
input
);
input
.
Position
=
0
;
_wire
.
Execute
(
method
,
_mimeType
,
input
,
_mimeType
,
output
);
//Read from _mimeType format
output
.
Position
=
0
;
response
.
MergeFrom
(
Options
,
_mimeType
,
output
);
return
response
.
Build
();
}
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestClientServerWithJsonFormat
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
ISearchService
client
=
new
SearchService
(
new
ExampleClient
(
wire
,
"text/json"
));
//now the client has a real, typed, interface to work with:
SearchResponse
result
=
client
.
Search
(
SearchRequest
.
CreateBuilder
().
AddCriteria
(
"Test"
).
Build
());
Assert
.
AreEqual
(
1
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
//The test part of this, call the only other method
result
=
client
.
RefineSearch
(
RefineSearchRequest
.
CreateBuilder
().
SetPreviousResults
(
result
).
AddCriteria
(
"Refine"
).
Build
());
Assert
.
AreEqual
(
2
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
Assert
.
AreEqual
(
"Refine"
,
result
.
ResultsList
[
1
].
Name
);
Assert
.
AreEqual
(
"http://refine.com"
,
result
.
ResultsList
[
1
].
Url
);
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestClientServerWithXmlFormat
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
ISearchService
client
=
new
SearchService
(
new
ExampleClient
(
wire
,
"text/xml"
));
//now the client has a real, typed, interface to work with:
SearchResponse
result
=
client
.
Search
(
SearchRequest
.
CreateBuilder
().
AddCriteria
(
"Test"
).
Build
());
Assert
.
AreEqual
(
1
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
//The test part of this, call the only other method
result
=
client
.
RefineSearch
(
RefineSearchRequest
.
CreateBuilder
().
SetPreviousResults
(
result
).
AddCriteria
(
"Refine"
).
Build
());
Assert
.
AreEqual
(
2
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
Assert
.
AreEqual
(
"Refine"
,
result
.
ResultsList
[
1
].
Name
);
Assert
.
AreEqual
(
"http://refine.com"
,
result
.
ResultsList
[
1
].
Url
);
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestClientServerWithProtoFormat
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
ISearchService
client
=
new
SearchService
(
new
ExampleClient
(
wire
,
"application/x-protobuf"
));
//now the client has a real, typed, interface to work with:
SearchResponse
result
=
client
.
Search
(
SearchRequest
.
CreateBuilder
().
AddCriteria
(
"Test"
).
Build
());
Assert
.
AreEqual
(
1
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
//The test part of this, call the only other method
result
=
client
.
RefineSearch
(
RefineSearchRequest
.
CreateBuilder
().
SetPreviousResults
(
result
).
AddCriteria
(
"Refine"
).
Build
());
Assert
.
AreEqual
(
2
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
Assert
.
AreEqual
(
"Refine"
,
result
.
ResultsList
[
1
].
Name
);
Assert
.
AreEqual
(
"http://refine.com"
,
result
.
ResultsList
[
1
].
Url
);
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestClientServerWithCustomFormat
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//Setup our custom mime-type format as the only format supported:
server
.
Options
.
MimeInputTypes
.
Clear
();
server
.
Options
.
MimeInputTypes
.
Add
(
"foo/bar"
,
CodedInputStream
.
CreateInstance
);
server
.
Options
.
MimeOutputTypes
.
Clear
();
server
.
Options
.
MimeOutputTypes
.
Add
(
"foo/bar"
,
CodedOutputStream
.
CreateInstance
);
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
ExampleClient
exclient
=
new
ExampleClient
(
wire
,
"foo/bar"
);
//Add our custom mime-type format
exclient
.
Options
.
MimeInputTypes
.
Add
(
"foo/bar"
,
CodedInputStream
.
CreateInstance
);
exclient
.
Options
.
MimeOutputTypes
.
Add
(
"foo/bar"
,
CodedOutputStream
.
CreateInstance
);
ISearchService
client
=
new
SearchService
(
exclient
);
//now the client has a real, typed, interface to work with:
SearchResponse
result
=
client
.
Search
(
SearchRequest
.
CreateBuilder
().
AddCriteria
(
"Test"
).
Build
());
Assert
.
AreEqual
(
1
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
//The test part of this, call the only other method
result
=
client
.
RefineSearch
(
RefineSearchRequest
.
CreateBuilder
().
SetPreviousResults
(
result
).
AddCriteria
(
"Refine"
).
Build
());
Assert
.
AreEqual
(
2
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
Assert
.
AreEqual
(
"Refine"
,
result
.
ResultsList
[
1
].
Name
);
Assert
.
AreEqual
(
"http://refine.com"
,
result
.
ResultsList
[
1
].
Url
);
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestServerWithUriFormat
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
MemoryStream
input
=
new
MemoryStream
(
Encoding
.
UTF8
.
GetBytes
(
"?Criteria=Test&Criteria=Test+of%20URI"
));
MemoryStream
output
=
new
MemoryStream
();
//Call the server
wire
.
Execute
(
"Search"
,
MessageFormatOptions
.
ContentFormUrlEncoded
,
input
,
MessageFormatOptions
.
ContentTypeProtoBuffer
,
output
);
SearchResponse
result
=
SearchResponse
.
ParseFrom
(
output
.
ToArray
());
Assert
.
AreEqual
(
2
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
Assert
.
AreEqual
(
"Test of URI"
,
result
.
ResultsList
[
1
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
1
].
Url
);
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
,
ExpectedException
(
typeof
(
ArgumentOutOfRangeException
))]
public
void
TestInvalidMimeType
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
MemoryStream
input
=
new
MemoryStream
();
MemoryStream
output
=
new
MemoryStream
();
//Call the server
wire
.
Execute
(
"Search"
,
"bad/mime"
,
input
,
MessageFormatOptions
.
ContentTypeProtoBuffer
,
output
);
Assert
.
Fail
();
}
/// <summary>
/// Test sending and recieving messages via text/json
/// </summary>
[
Test
]
public
void
TestDefaultMimeType
()
{
ExampleHttpServer
server
=
new
ExampleHttpServer
(
new
ExampleSearchImpl
());
//obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
IHttpTransfer
wire
=
server
;
MemoryStream
input
=
new
MemoryStream
(
new
SearchRequest
.
Builder
().
AddCriteria
(
"Test"
).
Build
().
ToByteArray
());
MemoryStream
output
=
new
MemoryStream
();
//With this default set, any invalid/unknown mime-type will be mapped to use that format
server
.
Options
.
DefaultContentType
=
MessageFormatOptions
.
ContentTypeProtoBuffer
;
wire
.
Execute
(
"Search"
,
"foo"
,
input
,
"bar"
,
output
);
SearchResponse
result
=
SearchResponse
.
ParseFrom
(
output
.
ToArray
());
Assert
.
AreEqual
(
1
,
result
.
ResultsCount
);
Assert
.
AreEqual
(
"Test"
,
result
.
ResultsList
[
0
].
Name
);
Assert
.
AreEqual
(
"http://search.com"
,
result
.
ResultsList
[
0
].
Url
);
}
}
}
\ No newline at end of file
src/ProtocolBuffers.Test/TestWriterFormatJson.cs
View file @
247c7534
...
@@ -10,6 +10,70 @@ namespace Google.ProtocolBuffers
...
@@ -10,6 +10,70 @@ namespace Google.ProtocolBuffers
[
TestFixture
]
[
TestFixture
]
public
class
TestWriterFormatJson
public
class
TestWriterFormatJson
{
{
[
Test
]
public
void
Example_FromJson
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
builder
.
MergeFromJson
(
@"{""valid"":true}"
);
TestXmlMessage
message
=
builder
.
Build
();
Assert
.
AreEqual
(
true
,
message
.
Valid
);
}
[
Test
]
public
void
Example_ToJson
()
{
TestXmlMessage
message
=
TestXmlMessage
.
CreateBuilder
()
.
SetValid
(
true
)
.
Build
();
string
json
=
message
.
ToJson
();
Assert
.
AreEqual
(
@"{""valid"":true}"
,
json
);
}
[
Test
]
public
void
Example_WriteJsonUsingICodedOutputStream
()
{
TestXmlMessage
message
=
TestXmlMessage
.
CreateBuilder
()
.
SetValid
(
true
)
.
Build
();
using
(
TextWriter
output
=
new
StringWriter
())
{
ICodedOutputStream
writer
=
JsonFormatWriter
.
CreateInstance
(
output
);
writer
.
WriteMessageStart
();
//manually begin the message, output is '{'
writer
.
Flush
();
Assert
.
AreEqual
(
"{"
,
output
.
ToString
());
ICodedOutputStream
stream
=
writer
;
message
.
WriteTo
(
stream
);
//write the message normally
writer
.
Flush
();
Assert
.
AreEqual
(
@"{""valid"":true"
,
output
.
ToString
());
writer
.
WriteMessageEnd
();
//manually write the end message '}'
Assert
.
AreEqual
(
@"{""valid"":true}"
,
output
.
ToString
());
}
}
[
Test
]
public
void
Example_ReadJsonUsingICodedInputStream
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
ICodedInputStream
reader
=
JsonFormatReader
.
CreateInstance
(
@"{""valid"":true}"
);
reader
.
ReadMessageStart
();
//manually read the begin the message '{'
builder
.
MergeFrom
(
reader
);
//write the message normally
reader
.
ReadMessageEnd
();
//manually read the end message '}'
}
protected
string
Content
;
protected
string
Content
;
[
System
.
Diagnostics
.
DebuggerNonUserCode
]
[
System
.
Diagnostics
.
DebuggerNonUserCode
]
protected
void
FormatterAssert
<
TMessage
>(
TMessage
message
,
params
string
[]
expecting
)
where
TMessage
:
IMessageLite
protected
void
FormatterAssert
<
TMessage
>(
TMessage
message
,
params
string
[]
expecting
)
where
TMessage
:
IMessageLite
...
@@ -337,6 +401,28 @@ namespace Google.ProtocolBuffers
...
@@ -337,6 +401,28 @@ namespace Google.ProtocolBuffers
Assert
.
AreEqual
(
3
,
ordinal
);
Assert
.
AreEqual
(
3
,
ordinal
);
Assert
.
AreEqual
(
3
,
builder
.
TextlinesCount
);
Assert
.
AreEqual
(
3
,
builder
.
TextlinesCount
);
}
}
[
Test
]
public
void
TestReadWriteJsonWithoutRoot
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
TestXmlMessage
message
=
builder
.
SetText
(
"abc"
).
SetNumber
(
123
).
Build
();
string
Json
;
using
(
StringWriter
sw
=
new
StringWriter
())
{
ICodedOutputStream
output
=
JsonFormatWriter
.
CreateInstance
(
sw
);
message
.
WriteTo
(
output
);
output
.
Flush
();
Json
=
sw
.
ToString
();
}
Assert
.
AreEqual
(
@"""text"":""abc"",""number"":123"
,
Json
);
ICodedInputStream
input
=
JsonFormatReader
.
CreateInstance
(
Json
);
TestXmlMessage
copy
=
TestXmlMessage
.
CreateBuilder
().
MergeFrom
(
input
).
Build
();
Assert
.
AreEqual
(
message
,
copy
);
}
[
Test
,
ExpectedException
(
typeof
(
RecursionLimitExceededException
))]
[
Test
,
ExpectedException
(
typeof
(
RecursionLimitExceededException
))]
public
void
TestRecursiveLimit
()
public
void
TestRecursiveLimit
()
{
{
...
...
src/ProtocolBuffers.Test/TestWriterFormatXml.cs
View file @
247c7534
...
@@ -12,6 +12,65 @@ namespace Google.ProtocolBuffers
...
@@ -12,6 +12,65 @@ namespace Google.ProtocolBuffers
[
TestFixture
]
[
TestFixture
]
public
class
TestWriterFormatXml
public
class
TestWriterFormatXml
{
{
[
Test
]
public
void
Example_FromXml
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
XmlReader
rdr
=
XmlReader
.
Create
(
new
StringReader
(
@"<root><valid>true</valid></root>"
));
builder
.
MergeFromXml
(
rdr
);
TestXmlMessage
message
=
builder
.
Build
();
Assert
.
AreEqual
(
true
,
message
.
Valid
);
}
[
Test
]
public
void
Example_ToXml
()
{
TestXmlMessage
message
=
TestXmlMessage
.
CreateBuilder
()
.
SetValid
(
true
)
.
Build
();
string
Xml
=
message
.
ToXml
();
Assert
.
AreEqual
(
@"<root><valid>true</valid></root>"
,
Xml
);
}
[
Test
]
public
void
Example_WriteXmlUsingICodedOutputStream
()
{
TestXmlMessage
message
=
TestXmlMessage
.
CreateBuilder
()
.
SetValid
(
true
)
.
Build
();
using
(
TextWriter
output
=
new
StringWriter
())
{
ICodedOutputStream
writer
=
XmlFormatWriter
.
CreateInstance
(
output
);
writer
.
WriteMessageStart
();
//manually begin the message, output is '{'
ICodedOutputStream
stream
=
writer
;
message
.
WriteTo
(
stream
);
//write the message normally
writer
.
WriteMessageEnd
();
//manually write the end message '}'
Assert
.
AreEqual
(
@"<root><valid>true</valid></root>"
,
output
.
ToString
());
}
}
[
Test
]
public
void
Example_ReadXmlUsingICodedInputStream
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
ICodedInputStream
reader
=
XmlFormatReader
.
CreateInstance
(
@"<root><valid>true</valid></root>"
);
reader
.
ReadMessageStart
();
//manually read the begin the message '{'
builder
.
MergeFrom
(
reader
);
//read the message normally
reader
.
ReadMessageEnd
();
//manually read the end message '}'
}
[
Test
]
[
Test
]
public
void
TestToXmlParseFromXml
()
public
void
TestToXmlParseFromXml
()
{
{
...
@@ -135,7 +194,9 @@ namespace Google.ProtocolBuffers
...
@@ -135,7 +194,9 @@ namespace Google.ProtocolBuffers
.
Build
();
.
Build
();
StringWriter
sw
=
new
StringWriter
();
StringWriter
sw
=
new
StringWriter
();
XmlFormatWriter
.
CreateInstance
(
sw
).
WriteMessage
(
"root"
,
message
);
XmlWriter
xwtr
=
XmlWriter
.
Create
(
sw
,
new
XmlWriterSettings
{
Indent
=
true
,
IndentChars
=
" "
});
XmlFormatWriter
.
CreateInstance
(
xwtr
).
WriteMessage
(
"root"
,
message
);
string
xml
=
sw
.
ToString
();
string
xml
=
sw
.
ToString
();
...
@@ -162,7 +223,9 @@ namespace Google.ProtocolBuffers
...
@@ -162,7 +223,9 @@ namespace Google.ProtocolBuffers
.
Build
();
.
Build
();
StringWriter
sw
=
new
StringWriter
();
StringWriter
sw
=
new
StringWriter
();
XmlFormatWriter
.
CreateInstance
(
sw
)
XmlWriter
xwtr
=
XmlWriter
.
Create
(
sw
,
new
XmlWriterSettings
{
Indent
=
true
,
IndentChars
=
" "
});
XmlFormatWriter
.
CreateInstance
(
xwtr
)
.
SetOptions
(
XmlWriterOptions
.
OutputNestedArrays
|
XmlWriterOptions
.
OutputEnumValues
)
.
SetOptions
(
XmlWriterOptions
.
OutputNestedArrays
|
XmlWriterOptions
.
OutputEnumValues
)
.
WriteMessage
(
"root"
,
message
);
.
WriteMessage
(
"root"
,
message
);
...
@@ -324,6 +387,60 @@ namespace Google.ProtocolBuffers
...
@@ -324,6 +387,60 @@ namespace Google.ProtocolBuffers
TestXmlMessage
copy
=
rdr
.
Merge
(
TestXmlMessage
.
CreateBuilder
(),
registry
).
Build
();
TestXmlMessage
copy
=
rdr
.
Merge
(
TestXmlMessage
.
CreateBuilder
(),
registry
).
Build
();
Assert
.
AreEqual
(
message
,
copy
);
Assert
.
AreEqual
(
message
,
copy
);
}
}
[
Test
]
public
void
TestXmlReadEmptyRoot
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
ICodedInputStream
reader
=
XmlFormatReader
.
CreateInstance
(
@"<root/>"
);
reader
.
ReadMessageStart
();
//manually read the begin the message '{'
builder
.
MergeFrom
(
reader
);
//write the message normally
reader
.
ReadMessageEnd
();
//manually read the end message '}'
}
[
Test
]
public
void
TestXmlReadEmptyChild
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
ICodedInputStream
reader
=
XmlFormatReader
.
CreateInstance
(
@"<root><text /></root>"
);
reader
.
ReadMessageStart
();
//manually read the begin the message '{'
builder
.
MergeFrom
(
reader
);
//write the message normally
Assert
.
IsTrue
(
builder
.
HasText
);
Assert
.
AreEqual
(
String
.
Empty
,
builder
.
Text
);
}
[
Test
]
public
void
TestXmlReadWriteWithoutRoot
()
{
TestXmlMessage
.
Builder
builder
=
TestXmlMessage
.
CreateBuilder
();
TestXmlMessage
message
=
builder
.
SetText
(
"abc"
).
SetNumber
(
123
).
Build
();
string
xml
;
using
(
StringWriter
sw
=
new
StringWriter
())
{
ICodedOutputStream
output
=
XmlFormatWriter
.
CreateInstance
(
XmlWriter
.
Create
(
sw
,
new
XmlWriterSettings
()
{
ConformanceLevel
=
ConformanceLevel
.
Fragment
}));
message
.
WriteTo
(
output
);
output
.
Flush
();
xml
=
sw
.
ToString
();
}
Assert
.
AreEqual
(
"<text>abc</text><number>123</number>"
,
xml
);
TestXmlMessage
copy
;
using
(
XmlReader
xr
=
XmlReader
.
Create
(
new
StringReader
(
xml
),
new
XmlReaderSettings
()
{
ConformanceLevel
=
ConformanceLevel
.
Fragment
}))
{
ICodedInputStream
input
=
XmlFormatReader
.
CreateInstance
(
xr
);
copy
=
TestXmlMessage
.
CreateBuilder
().
MergeFrom
(
input
).
Build
();
}
Assert
.
AreEqual
(
message
,
copy
);
}
[
Test
,
ExpectedException
(
typeof
(
RecursionLimitExceededException
))]
[
Test
,
ExpectedException
(
typeof
(
RecursionLimitExceededException
))]
public
void
TestRecursiveLimit
()
public
void
TestRecursiveLimit
()
{
{
...
...
src/ProtocolBuffers/CodedInputStream.cs
View file @
247c7534
...
@@ -144,6 +144,9 @@ namespace Google.ProtocolBuffers
...
@@ -144,6 +144,9 @@ namespace Google.ProtocolBuffers
#
endregion
#
endregion
void
ICodedInputStream
.
ReadMessageStart
()
{
}
void
ICodedInputStream
.
ReadMessageEnd
()
{
}
#
region
Validation
#
region
Validation
/// <summary>
/// <summary>
...
...
src/ProtocolBuffers/CodedOutputStream.cs
View file @
247c7534
...
@@ -125,6 +125,9 @@ namespace Google.ProtocolBuffers
...
@@ -125,6 +125,9 @@ namespace Google.ProtocolBuffers
}
}
#
endregion
#
endregion
void
ICodedOutputStream
.
WriteMessageStart
()
{
}
void
ICodedOutputStream
.
WriteMessageEnd
()
{
Flush
();
}
#
region
Writing
of
unknown
fields
#
region
Writing
of
unknown
fields
...
...
src/ProtocolBuffers/ICodedInputStream.cs
View file @
247c7534
...
@@ -45,6 +45,24 @@ namespace Google.ProtocolBuffers
...
@@ -45,6 +45,24 @@ namespace Google.ProtocolBuffers
{
{
public
interface
ICodedInputStream
public
interface
ICodedInputStream
{
{
/// <summary>
/// Reads any message initialization data expected from the input stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void
ReadMessageStart
();
/// <summary>
/// Reads any message finalization data expected from the input stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void
ReadMessageEnd
();
/// <summary>
/// <summary>
/// Attempt to read a field tag, returning false if we have reached the end
/// Attempt to read a field tag, returning false if we have reached the end
/// of the input data.
/// of the input data.
...
...
src/ProtocolBuffers/ICodedOutputStream.cs
View file @
247c7534
...
@@ -51,6 +51,24 @@ namespace Google.ProtocolBuffers
...
@@ -51,6 +51,24 @@ namespace Google.ProtocolBuffers
/// </summary>
/// </summary>
public
interface
ICodedOutputStream
public
interface
ICodedOutputStream
{
{
/// <summary>
/// Writes any message initialization data needed to the output stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void
WriteMessageStart
();
/// <summary>
/// Writes any message finalization data needed to the output stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void
WriteMessageEnd
();
/// <summary>
/// <summary>
/// Indicates that all temporary buffers be written to the final output.
/// Indicates that all temporary buffers be written to the final output.
/// </summary>
/// </summary>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment