mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-24 20:28:59 +08:00
2050 lines
72 KiB
C#
2050 lines
72 KiB
C#
#region copyright
|
||
//------------------------------------------------------------------------------
|
||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||
// QQ群:605534569
|
||
//------------------------------------------------------------------------------
|
||
#endregion
|
||
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System.Xml;
|
||
|
||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||
namespace Opc.Ua
|
||
{
|
||
public class OPCUAJsonEncoder : IJsonEncoder, IEncoder, IDisposable
|
||
{
|
||
private const int kStreamWriterBufferSize = 1024;
|
||
|
||
private Stream m_stream;
|
||
|
||
private MemoryStream m_memoryStream;
|
||
|
||
private StreamWriter m_writer;
|
||
|
||
private Stack<string> m_namespaces;
|
||
|
||
private bool m_commaRequired;
|
||
|
||
private bool m_inVariantWithEncoding;
|
||
|
||
private IServiceMessageContext m_context;
|
||
|
||
private ushort[] m_namespaceMappings;
|
||
|
||
private ushort[] m_serverMappings;
|
||
|
||
private uint m_nestingLevel;
|
||
|
||
private bool m_topLevelIsArray;
|
||
|
||
private bool m_levelOneSkipped;
|
||
|
||
private bool m_dontWriteClosing;
|
||
|
||
private bool m_leaveOpen;
|
||
|
||
private static readonly char[] m_specialChars = new char[7] { '"', '\\', '\n', '\r', '\t', '\b', '\f' };
|
||
|
||
private static readonly char[] m_substitution = new char[7] { '"', '\\', 'n', 'r', 't', 'b', 'f' };
|
||
|
||
public EncodingType EncodingType => EncodingType.Json;
|
||
|
||
public IServiceMessageContext Context => m_context;
|
||
|
||
public bool UseReversibleEncoding { get; private set; }
|
||
|
||
public bool ForceNamespaceUri { get; set; }
|
||
|
||
public bool ForceNamespaceUriForIndex1 { get; set; }
|
||
|
||
public bool IncludeDefaultValues { get; set; }
|
||
|
||
public bool IncludeDefaultNumberValues { get; set; }
|
||
|
||
public OPCUAJsonEncoder(IServiceMessageContext context, bool useReversibleEncoding)
|
||
: this(context, useReversibleEncoding, topLevelIsArray: false, null, leaveOpen: false, 1024)
|
||
{
|
||
}
|
||
|
||
public OPCUAJsonEncoder(IServiceMessageContext context, bool useReversibleEncoding, bool topLevelIsArray = false, Stream stream = null, bool leaveOpen = false, int streamSize = 1024)
|
||
{
|
||
Initialize();
|
||
m_context = context;
|
||
m_stream = stream;
|
||
m_leaveOpen = leaveOpen;
|
||
UseReversibleEncoding = useReversibleEncoding;
|
||
m_topLevelIsArray = topLevelIsArray;
|
||
if (m_stream == null)
|
||
{
|
||
m_memoryStream = new MemoryStream();
|
||
m_writer = new StreamWriter(m_memoryStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), streamSize, leaveOpen: false);
|
||
m_leaveOpen = false;
|
||
}
|
||
else
|
||
{
|
||
m_writer = new StreamWriter(m_stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), streamSize, m_leaveOpen);
|
||
}
|
||
InitializeWriter();
|
||
}
|
||
|
||
public OPCUAJsonEncoder(IServiceMessageContext context, bool useReversibleEncoding, StreamWriter writer, bool topLevelIsArray = false)
|
||
{
|
||
Initialize();
|
||
m_context = context;
|
||
m_writer = writer;
|
||
UseReversibleEncoding = useReversibleEncoding;
|
||
m_topLevelIsArray = topLevelIsArray;
|
||
if (m_writer == null)
|
||
{
|
||
m_stream = new MemoryStream();
|
||
m_writer = new StreamWriter(m_stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), 1024);
|
||
}
|
||
InitializeWriter();
|
||
}
|
||
|
||
private void Initialize()
|
||
{
|
||
m_stream = null;
|
||
m_writer = null;
|
||
m_namespaces = new Stack<string>();
|
||
m_commaRequired = false;
|
||
m_leaveOpen = false;
|
||
m_nestingLevel = 0u;
|
||
m_levelOneSkipped = false;
|
||
ForceNamespaceUri = false;
|
||
IncludeDefaultValues = false;
|
||
IncludeDefaultNumberValues = true;
|
||
}
|
||
|
||
private void InitializeWriter()
|
||
{
|
||
if (m_topLevelIsArray)
|
||
{
|
||
m_writer.Write("[");
|
||
}
|
||
else
|
||
{
|
||
m_writer.Write("{");
|
||
}
|
||
}
|
||
|
||
public static void EncodeSessionLessMessage(IEncodeable message, Stream stream, IServiceMessageContext context, bool leaveOpen)
|
||
{
|
||
if (message == null)
|
||
{
|
||
throw new ArgumentNullException("message");
|
||
}
|
||
if (context == null)
|
||
{
|
||
throw new ArgumentNullException("context");
|
||
}
|
||
OPCUAJsonEncoder jsonEncoder = new OPCUAJsonEncoder(context, useReversibleEncoding: true, topLevelIsArray: false, stream, leaveOpen);
|
||
try
|
||
{
|
||
long position = stream.Position;
|
||
SessionLessServiceMessage sessionLessServiceMessage = new SessionLessServiceMessage();
|
||
sessionLessServiceMessage.NamespaceUris = context.NamespaceUris;
|
||
sessionLessServiceMessage.ServerUris = context.ServerUris;
|
||
sessionLessServiceMessage.Message = message;
|
||
sessionLessServiceMessage.Encode(jsonEncoder);
|
||
if (context.MaxMessageSize > 0 && context.MaxMessageSize < (int)(stream.Position - position))
|
||
{
|
||
throw ServiceResultException.Create(2148007936u, "MaxMessageSize {0} < {1}", context.MaxMessageSize, (int)(stream.Position - position));
|
||
}
|
||
jsonEncoder.Close();
|
||
}
|
||
finally
|
||
{
|
||
if (leaveOpen)
|
||
{
|
||
stream.Position = 0L;
|
||
}
|
||
jsonEncoder.Dispose();
|
||
}
|
||
}
|
||
|
||
public static ArraySegment<byte> EncodeMessage(IEncodeable message, byte[] buffer, IServiceMessageContext context)
|
||
{
|
||
if (message == null)
|
||
{
|
||
throw new ArgumentNullException("message");
|
||
}
|
||
if (buffer == null)
|
||
{
|
||
throw new ArgumentNullException("buffer");
|
||
}
|
||
if (context == null)
|
||
{
|
||
throw new ArgumentNullException("context");
|
||
}
|
||
using MemoryStream stream = new MemoryStream(buffer, writable: true);
|
||
using OPCUAJsonEncoder jsonEncoder = new OPCUAJsonEncoder(context, useReversibleEncoding: true, topLevelIsArray: false, stream);
|
||
jsonEncoder.EncodeMessage(message);
|
||
int count = jsonEncoder.Close();
|
||
return new ArraySegment<byte>(buffer, 0, count);
|
||
}
|
||
|
||
public void EncodeMessage(IEncodeable message)
|
||
{
|
||
if (message == null)
|
||
{
|
||
throw new ArgumentNullException("message");
|
||
}
|
||
NodeId value = ExpandedNodeId.ToNodeId(message.TypeId, m_context.NamespaceUris);
|
||
WriteNodeId("TypeId", value);
|
||
WriteEncodeable("Body", message, message.GetType());
|
||
}
|
||
|
||
public void SetMappingTables(NamespaceTable namespaceUris, StringTable serverUris)
|
||
{
|
||
m_namespaceMappings = null;
|
||
if (namespaceUris != null && m_context.NamespaceUris != null)
|
||
{
|
||
m_namespaceMappings = namespaceUris.CreateMapping(m_context.NamespaceUris, updateTable: false);
|
||
}
|
||
m_serverMappings = null;
|
||
if (serverUris != null && m_context.ServerUris != null)
|
||
{
|
||
m_serverMappings = serverUris.CreateMapping(m_context.ServerUris, updateTable: false);
|
||
}
|
||
}
|
||
|
||
public string CloseAndReturnText()
|
||
{
|
||
Close();
|
||
if (m_memoryStream == null)
|
||
{
|
||
MemoryStream memoryStream = m_stream as MemoryStream;
|
||
if (memoryStream != null)
|
||
{
|
||
return Encoding.UTF8.GetString(memoryStream.ToArray());
|
||
}
|
||
throw new NotSupportedException("Cannot get text from external stream. Use Close or MemoryStream instead.");
|
||
}
|
||
return Encoding.UTF8.GetString(m_memoryStream.ToArray());
|
||
}
|
||
|
||
public int Close()
|
||
{
|
||
if (!m_dontWriteClosing)
|
||
{
|
||
if (m_topLevelIsArray)
|
||
{
|
||
m_writer.Write("]");
|
||
}
|
||
else
|
||
{
|
||
m_writer.Write("}");
|
||
}
|
||
}
|
||
m_writer.Flush();
|
||
int result = (int)m_writer.BaseStream.Position;
|
||
m_writer.Dispose();
|
||
m_writer = null;
|
||
return result;
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
Dispose(disposing: true);
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
|
||
protected virtual void Dispose(bool disposing)
|
||
{
|
||
if (disposing)
|
||
{
|
||
if (m_writer != null)
|
||
{
|
||
Close();
|
||
}
|
||
if (!m_leaveOpen)
|
||
{
|
||
Utils.SilentDispose(m_memoryStream);
|
||
Utils.SilentDispose(m_stream);
|
||
m_memoryStream = null;
|
||
m_stream = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
public void PushStructure(string fieldName)
|
||
{
|
||
m_nestingLevel++;
|
||
if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
if (!string.IsNullOrEmpty(fieldName))
|
||
{
|
||
m_writer.Write("\"");
|
||
EscapeString(fieldName);
|
||
m_writer.Write("\":");
|
||
}
|
||
else if (!m_commaRequired && m_nestingLevel == 1 && !m_topLevelIsArray)
|
||
{
|
||
m_levelOneSkipped = true;
|
||
return;
|
||
}
|
||
m_commaRequired = false;
|
||
m_writer.Write("{");
|
||
}
|
||
|
||
public void PushArray(string fieldName)
|
||
{
|
||
m_nestingLevel++;
|
||
if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
if (!string.IsNullOrEmpty(fieldName))
|
||
{
|
||
m_writer.Write("\"");
|
||
EscapeString(fieldName);
|
||
m_writer.Write("\":");
|
||
}
|
||
else if (!m_commaRequired && m_nestingLevel == 1 && !m_topLevelIsArray)
|
||
{
|
||
m_levelOneSkipped = true;
|
||
return;
|
||
}
|
||
m_commaRequired = false;
|
||
m_writer.Write("[");
|
||
}
|
||
|
||
public void PopStructure()
|
||
{
|
||
if (m_nestingLevel > 1 || m_topLevelIsArray || (m_nestingLevel == 1 && !m_levelOneSkipped))
|
||
{
|
||
m_writer.Write("}");
|
||
m_commaRequired = true;
|
||
}
|
||
m_nestingLevel--;
|
||
}
|
||
|
||
public void PopArray()
|
||
{
|
||
if (m_nestingLevel > 1 || m_topLevelIsArray || (m_nestingLevel == 1 && !m_levelOneSkipped))
|
||
{
|
||
m_writer.Write("]");
|
||
m_commaRequired = true;
|
||
}
|
||
m_nestingLevel--;
|
||
}
|
||
|
||
public void UsingReversibleEncoding<T>(Action<string, T> action, string fieldName, T value, bool useReversibleEncoding)
|
||
{
|
||
bool useReversibleEncoding2 = UseReversibleEncoding;
|
||
try
|
||
{
|
||
UseReversibleEncoding = useReversibleEncoding;
|
||
action(fieldName, value);
|
||
}
|
||
finally
|
||
{
|
||
UseReversibleEncoding = useReversibleEncoding2;
|
||
}
|
||
}
|
||
|
||
public void PushNamespace(string namespaceUri)
|
||
{
|
||
m_namespaces.Push(namespaceUri);
|
||
}
|
||
|
||
public void PopNamespace()
|
||
{
|
||
m_namespaces.Pop();
|
||
}
|
||
|
||
private void EscapeString(string value)
|
||
{
|
||
foreach (char c in value)
|
||
{
|
||
bool flag = false;
|
||
for (int j = 0; j < m_specialChars.Length; j++)
|
||
{
|
||
if (m_specialChars[j] == c)
|
||
{
|
||
m_writer.Write('\\');
|
||
m_writer.Write(m_substitution[j]);
|
||
flag = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!flag)
|
||
{
|
||
if (c < ' ')
|
||
{
|
||
m_writer.Write("\\u");
|
||
m_writer.Write("{0:X4}", (int)c);
|
||
}
|
||
else
|
||
{
|
||
m_writer.Write(c);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void WriteSimpleField(string fieldName, string value, bool quotes)
|
||
{
|
||
if (!string.IsNullOrEmpty(fieldName))
|
||
{
|
||
if (value == null)
|
||
{
|
||
return;
|
||
}
|
||
if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
m_writer.Write("\"");
|
||
EscapeString(fieldName);
|
||
m_writer.Write("\":");
|
||
}
|
||
else if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
if (value != null)
|
||
{
|
||
if (quotes)
|
||
{
|
||
m_writer.Write("\"");
|
||
EscapeString(value);
|
||
m_writer.Write("\"");
|
||
}
|
||
else
|
||
{
|
||
m_writer.Write(value);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
m_writer.Write("null");
|
||
}
|
||
m_commaRequired = true;
|
||
}
|
||
|
||
public void WriteBoolean(string fieldName, bool value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && !value)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (value)
|
||
{
|
||
WriteSimpleField(fieldName, "true", quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, "false", quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteSByte(string fieldName, sbyte value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteByte(string fieldName, byte value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteInt16(string fieldName, short value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteUInt16(string fieldName, ushort value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteInt32(string fieldName, int value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteUInt32(string fieldName, uint value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteInt64(string fieldName, long value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0L)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteUInt64(string fieldName, ulong value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value == 0L)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(CultureInfo.InvariantCulture), quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteFloat(string fieldName, float value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value > -1.401298E-45f && value < float.Epsilon)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (float.IsNaN(value))
|
||
{
|
||
WriteSimpleField(fieldName, "NaN", quotes: true);
|
||
}
|
||
else if (float.IsPositiveInfinity(value))
|
||
{
|
||
WriteSimpleField(fieldName, "Infinity", quotes: true);
|
||
}
|
||
else if (float.IsNegativeInfinity(value))
|
||
{
|
||
WriteSimpleField(fieldName, "-Infinity", quotes: true);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString("R", CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteDouble(string fieldName, double value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultNumberValues && value > -4.94065645841247E-324 && value < double.Epsilon)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (double.IsNaN(value))
|
||
{
|
||
WriteSimpleField(fieldName, "NaN", quotes: true);
|
||
}
|
||
else if (double.IsPositiveInfinity(value))
|
||
{
|
||
WriteSimpleField(fieldName, "Infinity", quotes: true);
|
||
}
|
||
else if (double.IsNegativeInfinity(value))
|
||
{
|
||
WriteSimpleField(fieldName, "-Infinity", quotes: true);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString("R", CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
}
|
||
|
||
public void WriteString(string fieldName, string value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultValues && value == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value, quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteDateTime(string fieldName, DateTime value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultValues && value == DateTime.MinValue)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (value <= DateTime.MinValue)
|
||
{
|
||
WriteSimpleField(fieldName, "0001-01-01T00:00:00Z", quotes: true);
|
||
}
|
||
else if (value >= DateTime.MaxValue)
|
||
{
|
||
WriteSimpleField(fieldName, "9999-12-31T23:59:59Z", quotes: true);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture), quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteGuid(string fieldName, Uuid value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultValues && value == Uuid.Empty)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(), quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteGuid(string fieldName, Guid value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultValues && value == Guid.Empty)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.ToString(), quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteByteString(string fieldName, byte[] value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
if (m_context.MaxByteStringLength > 0 && m_context.MaxByteStringLength < value.Length)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
WriteSimpleField(fieldName, Convert.ToBase64String(value), quotes: true);
|
||
}
|
||
|
||
public void WriteXmlElement(string fieldName, XmlElement value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
string outerXml = value.OuterXml;
|
||
byte[] bytes = Encoding.UTF8.GetBytes(outerXml);
|
||
WriteSimpleField(fieldName, Convert.ToBase64String(bytes), quotes: true);
|
||
}
|
||
|
||
private void WriteNamespaceIndex(string fieldName, ushort namespaceIndex)
|
||
{
|
||
if (namespaceIndex == 0)
|
||
{
|
||
return;
|
||
}
|
||
if ((!UseReversibleEncoding || ForceNamespaceUri) && namespaceIndex > ((!ForceNamespaceUriForIndex1) ? 1 : 0))
|
||
{
|
||
string @string = m_context.NamespaceUris.GetString(namespaceIndex);
|
||
if (!string.IsNullOrEmpty(@string))
|
||
{
|
||
WriteSimpleField(fieldName, @string, quotes: true);
|
||
return;
|
||
}
|
||
}
|
||
if (m_namespaceMappings != null && m_namespaceMappings.Length > namespaceIndex)
|
||
{
|
||
namespaceIndex = m_namespaceMappings[namespaceIndex];
|
||
}
|
||
if (namespaceIndex != 0)
|
||
{
|
||
WriteUInt16(fieldName, namespaceIndex);
|
||
}
|
||
}
|
||
|
||
private void WriteNodeIdContents(NodeId value, string namespaceUri = null)
|
||
{
|
||
if (value.IdType > IdType.Numeric)
|
||
{
|
||
WriteInt32("IdType", (int)value.IdType);
|
||
}
|
||
switch (value.IdType)
|
||
{
|
||
case IdType.Numeric:
|
||
WriteUInt32("Id", (uint)value.Identifier);
|
||
break;
|
||
case IdType.String:
|
||
WriteString("Id", (string)value.Identifier);
|
||
break;
|
||
case IdType.Guid:
|
||
WriteGuid("Id", (Guid)value.Identifier);
|
||
break;
|
||
case IdType.Opaque:
|
||
WriteByteString("Id", (byte[])value.Identifier);
|
||
break;
|
||
}
|
||
if (namespaceUri != null)
|
||
{
|
||
WriteString("Namespace", namespaceUri);
|
||
}
|
||
else
|
||
{
|
||
WriteNamespaceIndex("Namespace", value.NamespaceIndex);
|
||
}
|
||
}
|
||
|
||
public void WriteNodeId(string fieldName, NodeId value)
|
||
{
|
||
if (value == null || (NodeId.IsNull(value) && value.IdType == IdType.Numeric))
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
ushort namespaceIndex = value.NamespaceIndex;
|
||
if (ForceNamespaceUri && namespaceIndex > ((!ForceNamespaceUriForIndex1) ? 1 : 0))
|
||
{
|
||
string @string = Context.NamespaceUris.GetString(namespaceIndex);
|
||
WriteNodeIdContents(value, @string);
|
||
}
|
||
else
|
||
{
|
||
WriteNodeIdContents(value);
|
||
}
|
||
PopStructure();
|
||
}
|
||
|
||
public void WriteExpandedNodeId(string fieldName, ExpandedNodeId value)
|
||
{
|
||
var nodeid = (((NodeId)value));
|
||
if (value == null || nodeid == null || (!UseReversibleEncoding && NodeId.IsNull(value)))
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
string text = value.NamespaceUri;
|
||
ushort namespaceIndex = value.NamespaceIndex;
|
||
if (ForceNamespaceUri && text == null && namespaceIndex > ((!ForceNamespaceUriForIndex1) ? 1 : 0))
|
||
{
|
||
text = Context.NamespaceUris.GetString(namespaceIndex);
|
||
}
|
||
WriteNodeIdContents(nodeid, text);
|
||
uint num = value.ServerIndex;
|
||
if (num >= 1)
|
||
{
|
||
string @string = m_context.ServerUris.GetString(num);
|
||
if (!string.IsNullOrEmpty(@string))
|
||
{
|
||
WriteSimpleField("ServerUri", @string, quotes: true);
|
||
PopStructure();
|
||
return;
|
||
}
|
||
if (m_serverMappings != null && m_serverMappings.Length > num)
|
||
{
|
||
num = m_serverMappings[num];
|
||
}
|
||
if (num != 0)
|
||
{
|
||
WriteUInt32("ServerUri", num);
|
||
}
|
||
}
|
||
PopStructure();
|
||
}
|
||
|
||
public void WriteStatusCode(string fieldName, StatusCode value)
|
||
{
|
||
if (fieldName != null && !IncludeDefaultValues && value == 0u)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (UseReversibleEncoding)
|
||
{
|
||
WriteUInt32(fieldName, value.Code);
|
||
}
|
||
else if (value != 0u)
|
||
{
|
||
PushStructure(fieldName);
|
||
WriteSimpleField("Code", value.Code.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
WriteSimpleField("Symbol", StatusCode.LookupSymbolicId(value.CodeBits), quotes: true);
|
||
PopStructure();
|
||
}
|
||
}
|
||
|
||
public void WriteDiagnosticInfo(string fieldName, DiagnosticInfo value)
|
||
{
|
||
WriteDiagnosticInfo(fieldName, value, 0);
|
||
}
|
||
|
||
public void WriteQualifiedName(string fieldName, QualifiedName value)
|
||
{
|
||
if (QualifiedName.IsNull(value))
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
WriteString("Name", value.Name);
|
||
WriteNamespaceIndex("Uri", value.NamespaceIndex);
|
||
PopStructure();
|
||
}
|
||
|
||
public void WriteLocalizedText(string fieldName, LocalizedText value)
|
||
{
|
||
if (LocalizedText.IsNullOrEmpty(value))
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (UseReversibleEncoding)
|
||
{
|
||
PushStructure(fieldName);
|
||
WriteSimpleField("Text", value.Text, quotes: true);
|
||
if (!string.IsNullOrEmpty(value.Locale))
|
||
{
|
||
WriteSimpleField("Locale", value.Locale, quotes: true);
|
||
}
|
||
PopStructure();
|
||
}
|
||
else
|
||
{
|
||
WriteSimpleField(fieldName, value.Text, quotes: true);
|
||
}
|
||
}
|
||
|
||
public void WriteVariant(string fieldName, Variant value)
|
||
{
|
||
if (Variant.Null == value)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
CheckAndIncrementNestingLevel();
|
||
try
|
||
{
|
||
bool flag = value.TypeInfo == null || value.TypeInfo.BuiltInType == BuiltInType.Null || value.Value == null;
|
||
if (UseReversibleEncoding && !flag)
|
||
{
|
||
PushStructure(fieldName);
|
||
byte value2 = (byte)value.TypeInfo.BuiltInType;
|
||
if (value.TypeInfo.BuiltInType == BuiltInType.Enumeration)
|
||
{
|
||
value2 = 6;
|
||
}
|
||
WriteByte("Type", value2);
|
||
fieldName = "Body";
|
||
}
|
||
if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
if (!string.IsNullOrEmpty(fieldName))
|
||
{
|
||
m_writer.Write("\"");
|
||
EscapeString(fieldName);
|
||
m_writer.Write("\":");
|
||
}
|
||
WriteVariantContents(value.Value, value.TypeInfo);
|
||
if (UseReversibleEncoding && !flag)
|
||
{
|
||
Matrix matrix = value.Value as Matrix;
|
||
if (matrix != null)
|
||
{
|
||
WriteInt32Array("Dimensions", matrix.Dimensions);
|
||
}
|
||
PopStructure();
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
m_nestingLevel--;
|
||
}
|
||
}
|
||
|
||
public void WriteDataValue(string fieldName, DataValue value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
if (value != null)
|
||
{
|
||
if (value.WrappedValue.TypeInfo != null && value.WrappedValue.TypeInfo.BuiltInType != 0)
|
||
{
|
||
WriteVariant("Value", value.WrappedValue);
|
||
}
|
||
if (value.StatusCode != 0u)
|
||
{
|
||
WriteStatusCode("StatusCode", value.StatusCode);
|
||
}
|
||
if (value.SourceTimestamp != DateTime.MinValue)
|
||
{
|
||
WriteDateTime("SourceTimestamp", value.SourceTimestamp);
|
||
if (value.SourcePicoseconds != 0)
|
||
{
|
||
WriteUInt16("SourcePicoseconds", value.SourcePicoseconds);
|
||
}
|
||
}
|
||
if (value.ServerTimestamp != DateTime.MinValue)
|
||
{
|
||
WriteDateTime("ServerTimestamp", value.ServerTimestamp);
|
||
if (value.ServerPicoseconds != 0)
|
||
{
|
||
WriteUInt16("ServerPicoseconds", value.ServerPicoseconds);
|
||
}
|
||
}
|
||
}
|
||
PopStructure();
|
||
}
|
||
|
||
public void WriteExtensionObject(string fieldName, ExtensionObject value)
|
||
{
|
||
if (value == null || value.Encoding == ExtensionObjectEncoding.None)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
IEncodeable encodeable = value.Body as IEncodeable;
|
||
if (!UseReversibleEncoding && encodeable != null)
|
||
{
|
||
IStructureTypeInfo structureTypeInfo = value.Body as IStructureTypeInfo;
|
||
if (structureTypeInfo != null && structureTypeInfo.StructureType == StructureType.Union)
|
||
{
|
||
encodeable.Encode(this);
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
encodeable.Encode(this);
|
||
PopStructure();
|
||
return;
|
||
}
|
||
PushStructure(fieldName);
|
||
ExpandedNodeId expandedNodeId = value.TypeId;
|
||
if (encodeable != null)
|
||
{
|
||
expandedNodeId = value.Encoding switch
|
||
{
|
||
ExtensionObjectEncoding.Binary => encodeable.BinaryEncodingId,
|
||
ExtensionObjectEncoding.Xml => encodeable.XmlEncodingId,
|
||
_ => encodeable.TypeId,
|
||
};
|
||
}
|
||
NodeId value2 = ExpandedNodeId.ToNodeId(expandedNodeId, Context.NamespaceUris);
|
||
if (UseReversibleEncoding)
|
||
{
|
||
WriteNodeId("TypeId", value2);
|
||
}
|
||
else
|
||
{
|
||
WriteExpandedNodeId("TypeId", expandedNodeId);
|
||
}
|
||
if (encodeable != null)
|
||
{
|
||
WriteEncodeable("Body", encodeable, null);
|
||
}
|
||
else if (value.Body != null)
|
||
{
|
||
if (value.Encoding == ExtensionObjectEncoding.Json)
|
||
{
|
||
WriteSimpleField("Body", value.Body as string, quotes: true);
|
||
}
|
||
else
|
||
{
|
||
WriteByte("Encoding", (byte)value.Encoding);
|
||
if (value.Encoding == ExtensionObjectEncoding.Binary)
|
||
{
|
||
WriteByteString("Body", value.Body as byte[]);
|
||
}
|
||
else if (value.Encoding == ExtensionObjectEncoding.Xml)
|
||
{
|
||
WriteXmlElement("Body", value.Body as XmlElement);
|
||
}
|
||
}
|
||
}
|
||
PopStructure();
|
||
}
|
||
|
||
public void WriteEncodeable(string fieldName, IEncodeable value, Type systemType)
|
||
{
|
||
if (value == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
if (m_nestingLevel == 0 && (m_commaRequired || m_topLevelIsArray) && (string.IsNullOrWhiteSpace(fieldName) ^ m_topLevelIsArray))
|
||
{
|
||
throw ServiceResultException.Create(2147876864u, "With Array as top level, encodeables with fieldname will create invalid json");
|
||
}
|
||
if (m_nestingLevel == 0 && !m_commaRequired && string.IsNullOrWhiteSpace(fieldName) && !m_topLevelIsArray)
|
||
{
|
||
m_writer.Flush();
|
||
if (m_writer.BaseStream.Length == 1)
|
||
{
|
||
m_writer.BaseStream.Seek(0L, SeekOrigin.Begin);
|
||
}
|
||
m_dontWriteClosing = true;
|
||
}
|
||
CheckAndIncrementNestingLevel();
|
||
try
|
||
{
|
||
PushStructure(fieldName);
|
||
value?.Encode(this);
|
||
PopStructure();
|
||
}
|
||
finally
|
||
{
|
||
m_nestingLevel--;
|
||
}
|
||
}
|
||
|
||
public void WriteEnumerated(string fieldName, Enum value)
|
||
{
|
||
int num = Convert.ToInt32(value, CultureInfo.InvariantCulture);
|
||
string text = num.ToString();
|
||
if (UseReversibleEncoding)
|
||
{
|
||
WriteSimpleField(fieldName, text, quotes: false);
|
||
return;
|
||
}
|
||
if (value.ToString() == text)
|
||
{
|
||
WriteSimpleField(fieldName, text, quotes: true);
|
||
return;
|
||
}
|
||
WriteSimpleField(fieldName, Utils.Format("{0}_{1}", value.ToString(), num), quotes: true);
|
||
}
|
||
|
||
public void WriteEnumerated(string fieldName, int numeric)
|
||
{
|
||
string value = numeric.ToString(CultureInfo.InvariantCulture);
|
||
WriteSimpleField(fieldName, value, !UseReversibleEncoding);
|
||
}
|
||
|
||
public void WriteBooleanArray(string fieldName, IList<bool> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteBoolean(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteSByteArray(string fieldName, IList<sbyte> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteSByte(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteByteArray(string fieldName, IList<byte> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteByte(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteInt16Array(string fieldName, IList<short> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteInt16(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteUInt16Array(string fieldName, IList<ushort> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteUInt16(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteInt32Array(string fieldName, IList<int> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteInt32(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteUInt32Array(string fieldName, IList<uint> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteUInt32(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteInt64Array(string fieldName, IList<long> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteInt64(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteUInt64Array(string fieldName, IList<ulong> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteUInt64(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteFloatArray(string fieldName, IList<float> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteFloat(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteDoubleArray(string fieldName, IList<double> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteDouble(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteStringArray(string fieldName, IList<string> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteString(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteDateTimeArray(string fieldName, IList<DateTime> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
if (values[i] <= DateTime.MinValue)
|
||
{
|
||
WriteSimpleField(null, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteDateTime(null, values[i]);
|
||
}
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteGuidArray(string fieldName, IList<Uuid> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteGuid(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteGuidArray(string fieldName, IList<Guid> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteGuid(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteByteStringArray(string fieldName, IList<byte[]> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteByteString(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteXmlElementArray(string fieldName, IList<XmlElement> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteXmlElement(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteNodeIdArray(string fieldName, IList<NodeId> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteNodeId(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteExpandedNodeIdArray(string fieldName, IList<ExpandedNodeId> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteExpandedNodeId(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteStatusCodeArray(string fieldName, IList<StatusCode> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
if (!UseReversibleEncoding && values[i] == 0u)
|
||
{
|
||
WriteSimpleField(null, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteStatusCode(null, values[i]);
|
||
}
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteDiagnosticInfoArray(string fieldName, IList<DiagnosticInfo> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteDiagnosticInfo(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteQualifiedNameArray(string fieldName, IList<QualifiedName> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteQualifiedName(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteLocalizedTextArray(string fieldName, IList<LocalizedText> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteLocalizedText(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteVariantArray(string fieldName, IList<Variant> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
if (values[i] == Variant.Null)
|
||
{
|
||
WriteSimpleField(null, null, quotes: false);
|
||
}
|
||
else
|
||
{
|
||
WriteVariant(null, values[i]);
|
||
}
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteDataValueArray(string fieldName, IList<DataValue> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteDataValue(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteExtensionObjectArray(string fieldName, IList<ExtensionObject> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteExtensionObject(null, values[i]);
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteEncodeableArray(string fieldName, IList<IEncodeable> values, Type systemType)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
}
|
||
else if (string.IsNullOrWhiteSpace(fieldName) && m_nestingLevel == 0 && !m_topLevelIsArray)
|
||
{
|
||
m_writer.Flush();
|
||
if (m_writer.BaseStream.Length == 1)
|
||
{
|
||
m_writer.BaseStream.Seek(0L, SeekOrigin.Begin);
|
||
}
|
||
m_nestingLevel++;
|
||
PushArray(fieldName);
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteEncodeable(null, values[i], systemType);
|
||
}
|
||
PopArray();
|
||
m_dontWriteClosing = true;
|
||
m_nestingLevel--;
|
||
}
|
||
else
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(fieldName) && m_nestingLevel == 0 && m_topLevelIsArray)
|
||
{
|
||
throw ServiceResultException.Create(2147876864u, "With Array as top level, encodeables array with filename will create invalid json");
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
for (int j = 0; j < values.Count; j++)
|
||
{
|
||
WriteEncodeable(null, values[j], systemType);
|
||
}
|
||
PopArray();
|
||
}
|
||
}
|
||
|
||
public void WriteEnumeratedArray(string fieldName, Array values, Type systemType)
|
||
{
|
||
if (values == null || values.Length == 0)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Length)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
Type elementType = values.GetType().GetElementType();
|
||
if (elementType.IsEnum)
|
||
{
|
||
foreach (Enum value in values)
|
||
{
|
||
WriteEnumerated(null, value);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (elementType != typeof(int))
|
||
{
|
||
throw new ServiceResultException(2147876864u, Utils.Format("Type '{0}' is not allowed in an Enumeration.", elementType.FullName));
|
||
}
|
||
foreach (int value2 in values)
|
||
{
|
||
WriteEnumerated(null, value2);
|
||
}
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteVariantContents(object value, TypeInfo typeInfo)
|
||
{
|
||
try
|
||
{
|
||
m_inVariantWithEncoding = UseReversibleEncoding;
|
||
if (value == null)
|
||
{
|
||
return;
|
||
}
|
||
m_commaRequired = false;
|
||
if (typeInfo.ValueRank < 0)
|
||
{
|
||
switch (typeInfo.BuiltInType)
|
||
{
|
||
case BuiltInType.Boolean:
|
||
WriteBoolean(null, (bool)value);
|
||
break;
|
||
case BuiltInType.SByte:
|
||
WriteSByte(null, (sbyte)value);
|
||
break;
|
||
case BuiltInType.Byte:
|
||
WriteByte(null, (byte)value);
|
||
break;
|
||
case BuiltInType.Int16:
|
||
WriteInt16(null, (short)value);
|
||
break;
|
||
case BuiltInType.UInt16:
|
||
WriteUInt16(null, (ushort)value);
|
||
break;
|
||
case BuiltInType.Int32:
|
||
WriteInt32(null, (int)value);
|
||
break;
|
||
case BuiltInType.UInt32:
|
||
WriteUInt32(null, (uint)value);
|
||
break;
|
||
case BuiltInType.Int64:
|
||
WriteInt64(null, (long)value);
|
||
break;
|
||
case BuiltInType.UInt64:
|
||
WriteUInt64(null, (ulong)value);
|
||
break;
|
||
case BuiltInType.Float:
|
||
WriteFloat(null, (float)value);
|
||
break;
|
||
case BuiltInType.Double:
|
||
WriteDouble(null, (double)value);
|
||
break;
|
||
case BuiltInType.String:
|
||
WriteString(null, (string)value);
|
||
break;
|
||
case BuiltInType.DateTime:
|
||
WriteDateTime(null, (DateTime)value);
|
||
break;
|
||
case BuiltInType.Guid:
|
||
WriteGuid(null, (Uuid)value);
|
||
break;
|
||
case BuiltInType.ByteString:
|
||
WriteByteString(null, (byte[])value);
|
||
break;
|
||
case BuiltInType.XmlElement:
|
||
WriteXmlElement(null, (XmlElement)value);
|
||
break;
|
||
case BuiltInType.NodeId:
|
||
WriteNodeId(null, (NodeId)value);
|
||
break;
|
||
case BuiltInType.ExpandedNodeId:
|
||
WriteExpandedNodeId(null, (ExpandedNodeId)value);
|
||
break;
|
||
case BuiltInType.StatusCode:
|
||
WriteStatusCode(null, (StatusCode)value);
|
||
break;
|
||
case BuiltInType.QualifiedName:
|
||
WriteQualifiedName(null, (QualifiedName)value);
|
||
break;
|
||
case BuiltInType.LocalizedText:
|
||
WriteLocalizedText(null, (LocalizedText)value);
|
||
break;
|
||
case BuiltInType.ExtensionObject:
|
||
WriteExtensionObject(null, (ExtensionObject)value);
|
||
break;
|
||
case BuiltInType.DataValue:
|
||
WriteDataValue(null, (DataValue)value);
|
||
break;
|
||
case BuiltInType.Enumeration:
|
||
WriteEnumerated(null, (Enum)value);
|
||
break;
|
||
case BuiltInType.DiagnosticInfo:
|
||
WriteDiagnosticInfo(null, (DiagnosticInfo)value);
|
||
break;
|
||
case BuiltInType.Variant:
|
||
case BuiltInType.Number:
|
||
case BuiltInType.Integer:
|
||
case BuiltInType.UInteger:
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (typeInfo.ValueRank < 1)
|
||
{
|
||
return;
|
||
}
|
||
int valueRank = typeInfo.ValueRank;
|
||
if (UseReversibleEncoding)
|
||
{
|
||
Matrix matrix = value as Matrix;
|
||
if (matrix != null)
|
||
{
|
||
value = matrix.Elements;
|
||
valueRank = 1;
|
||
}
|
||
}
|
||
WriteArray(null, value, valueRank, typeInfo.BuiltInType);
|
||
return;
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
m_inVariantWithEncoding = false;
|
||
}
|
||
}
|
||
|
||
public void WriteObjectArray(string fieldName, IList<object> values)
|
||
{
|
||
if (values == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
PushArray(fieldName);
|
||
if (values != null && m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
|
||
{
|
||
throw new ServiceResultException(2148007936u);
|
||
}
|
||
if (values != null)
|
||
{
|
||
for (int i = 0; i < values.Count; i++)
|
||
{
|
||
WriteVariant("Variant", new Variant(values[i]));
|
||
}
|
||
}
|
||
PopArray();
|
||
}
|
||
|
||
public void WriteArray(string fieldName, object array, int valueRank, BuiltInType builtInType)
|
||
{
|
||
if (valueRank == 1)
|
||
{
|
||
switch (builtInType)
|
||
{
|
||
case BuiltInType.Boolean:
|
||
WriteBooleanArray(fieldName, (bool[])array);
|
||
break;
|
||
case BuiltInType.SByte:
|
||
WriteSByteArray(fieldName, (sbyte[])array);
|
||
break;
|
||
case BuiltInType.Byte:
|
||
WriteByteArray(fieldName, (byte[])array);
|
||
break;
|
||
case BuiltInType.Int16:
|
||
WriteInt16Array(fieldName, (short[])array);
|
||
break;
|
||
case BuiltInType.UInt16:
|
||
WriteUInt16Array(fieldName, (ushort[])array);
|
||
break;
|
||
case BuiltInType.Int32:
|
||
WriteInt32Array(fieldName, (int[])array);
|
||
break;
|
||
case BuiltInType.UInt32:
|
||
WriteUInt32Array(fieldName, (uint[])array);
|
||
break;
|
||
case BuiltInType.Int64:
|
||
WriteInt64Array(fieldName, (long[])array);
|
||
break;
|
||
case BuiltInType.UInt64:
|
||
WriteUInt64Array(fieldName, (ulong[])array);
|
||
break;
|
||
case BuiltInType.Float:
|
||
WriteFloatArray(fieldName, (float[])array);
|
||
break;
|
||
case BuiltInType.Double:
|
||
WriteDoubleArray(fieldName, (double[])array);
|
||
break;
|
||
case BuiltInType.String:
|
||
WriteStringArray(fieldName, (string[])array);
|
||
break;
|
||
case BuiltInType.DateTime:
|
||
WriteDateTimeArray(fieldName, (DateTime[])array);
|
||
break;
|
||
case BuiltInType.Guid:
|
||
WriteGuidArray(fieldName, (Uuid[])array);
|
||
break;
|
||
case BuiltInType.ByteString:
|
||
WriteByteStringArray(fieldName, (byte[][])array);
|
||
break;
|
||
case BuiltInType.XmlElement:
|
||
WriteXmlElementArray(fieldName, (XmlElement[])array);
|
||
break;
|
||
case BuiltInType.NodeId:
|
||
WriteNodeIdArray(fieldName, (NodeId[])array);
|
||
break;
|
||
case BuiltInType.ExpandedNodeId:
|
||
WriteExpandedNodeIdArray(fieldName, (ExpandedNodeId[])array);
|
||
break;
|
||
case BuiltInType.StatusCode:
|
||
WriteStatusCodeArray(fieldName, (StatusCode[])array);
|
||
break;
|
||
case BuiltInType.QualifiedName:
|
||
WriteQualifiedNameArray(fieldName, (QualifiedName[])array);
|
||
break;
|
||
case BuiltInType.LocalizedText:
|
||
WriteLocalizedTextArray(fieldName, (LocalizedText[])array);
|
||
break;
|
||
case BuiltInType.ExtensionObject:
|
||
WriteExtensionObjectArray(fieldName, (ExtensionObject[])array);
|
||
break;
|
||
case BuiltInType.DataValue:
|
||
WriteDataValueArray(fieldName, (DataValue[])array);
|
||
break;
|
||
case BuiltInType.DiagnosticInfo:
|
||
WriteDiagnosticInfoArray(fieldName, (DiagnosticInfo[])array);
|
||
break;
|
||
case BuiltInType.Enumeration:
|
||
{
|
||
Array array6 = array as Array;
|
||
if (array6 == null)
|
||
{
|
||
throw ServiceResultException.Create(2147876864u, "Unexpected non Array type encountered while encoding an array of enumeration.");
|
||
}
|
||
WriteEnumeratedArray(fieldName, array6, array6.GetType().GetElementType());
|
||
break;
|
||
}
|
||
case BuiltInType.Variant:
|
||
{
|
||
Variant[] array3 = array as Variant[];
|
||
if (array3 != null)
|
||
{
|
||
WriteVariantArray(fieldName, array3);
|
||
break;
|
||
}
|
||
IEncodeable[] array4 = array as IEncodeable[];
|
||
if (array4 != null)
|
||
{
|
||
WriteEncodeableArray(fieldName, array4, array.GetType().GetElementType());
|
||
break;
|
||
}
|
||
object[] array5 = array as object[];
|
||
if (array5 != null)
|
||
{
|
||
WriteObjectArray(fieldName, array5);
|
||
break;
|
||
}
|
||
throw ServiceResultException.Create(2147876864u, "Unexpected type encountered while encoding an array of Variants: {0}", array.GetType());
|
||
}
|
||
default:
|
||
{
|
||
IEncodeable[] array2 = array as IEncodeable[];
|
||
if (array2 != null)
|
||
{
|
||
WriteEncodeableArray(fieldName, array2, array.GetType().GetElementType());
|
||
break;
|
||
}
|
||
if (array == null)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
break;
|
||
}
|
||
throw ServiceResultException.Create(2147876864u, "Unexpected BuiltInType encountered while encoding an array: {0}", builtInType);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (valueRank <= 1)
|
||
{
|
||
return;
|
||
}
|
||
Matrix matrix = array as Matrix;
|
||
if (matrix == null)
|
||
{
|
||
Array array7 = array as Array;
|
||
if (array7 == null || array7.Rank != valueRank)
|
||
{
|
||
throw ServiceResultException.Create(2147876864u, "Unexpected array type encountered while encoding array: {0}", array.GetType().Name);
|
||
}
|
||
matrix = new Matrix(array7, builtInType);
|
||
}
|
||
if (matrix != null)
|
||
{
|
||
int index = 0;
|
||
WriteStructureMatrix(fieldName, matrix, 0, ref index, matrix.TypeInfo);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void WriteDiagnosticInfo(string fieldName, DiagnosticInfo value, int depth)
|
||
{
|
||
if (value == null || value.IsNullDiagnosticInfo)
|
||
{
|
||
WriteSimpleField(fieldName, null, quotes: false);
|
||
return;
|
||
}
|
||
CheckAndIncrementNestingLevel();
|
||
try
|
||
{
|
||
PushStructure(fieldName);
|
||
if (value.SymbolicId >= 0)
|
||
{
|
||
WriteSimpleField("SymbolicId", value.SymbolicId.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
if (value.NamespaceUri >= 0)
|
||
{
|
||
WriteSimpleField("NamespaceUri", value.NamespaceUri.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
if (value.Locale >= 0)
|
||
{
|
||
WriteSimpleField("Locale", value.Locale.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
if (value.LocalizedText >= 0)
|
||
{
|
||
WriteSimpleField("LocalizedText", value.LocalizedText.ToString(CultureInfo.InvariantCulture), quotes: false);
|
||
}
|
||
if (value.AdditionalInfo != null)
|
||
{
|
||
WriteSimpleField("AdditionalInfo", value.AdditionalInfo, quotes: true);
|
||
}
|
||
if (value.InnerStatusCode != 0u)
|
||
{
|
||
WriteStatusCode("InnerStatusCode", value.InnerStatusCode);
|
||
}
|
||
if (value.InnerDiagnosticInfo != null)
|
||
{
|
||
if (depth < DiagnosticInfo.MaxInnerDepth)
|
||
{
|
||
WriteDiagnosticInfo("InnerDiagnosticInfo", value.InnerDiagnosticInfo, depth + 1);
|
||
}
|
||
else
|
||
{
|
||
Utils.LogWarning("InnerDiagnosticInfo dropped because nesting exceeds maximum of {0}.", DiagnosticInfo.MaxInnerDepth);
|
||
}
|
||
}
|
||
PopStructure();
|
||
}
|
||
finally
|
||
{
|
||
m_nestingLevel--;
|
||
}
|
||
}
|
||
|
||
private void WriteStructureMatrix(string fieldName, Matrix matrix, int dim, ref int index, TypeInfo typeInfo)
|
||
{
|
||
var (flag, num) = Matrix.ValidateDimensions(allowZeroDimension: true, matrix.Dimensions, Context.MaxArrayLength);
|
||
if (!flag || num != matrix.Elements.Length)
|
||
{
|
||
throw new ArgumentException("The number of elements in the matrix does not match the dimensions.");
|
||
}
|
||
CheckAndIncrementNestingLevel();
|
||
try
|
||
{
|
||
int num2 = matrix.Dimensions[dim];
|
||
if (dim == matrix.Dimensions.Length - 1)
|
||
{
|
||
Array array = Array.CreateInstance(matrix.Elements.GetType().GetElementType(), num2);
|
||
Array.Copy(matrix.Elements, index, array, 0, num2);
|
||
if (m_commaRequired)
|
||
{
|
||
m_writer.Write(",");
|
||
}
|
||
WriteVariantContents(array, new TypeInfo(typeInfo.BuiltInType, 1));
|
||
index += num2;
|
||
}
|
||
else
|
||
{
|
||
PushArray(fieldName);
|
||
for (int i = 0; i < num2; i++)
|
||
{
|
||
WriteStructureMatrix(null, matrix, dim + 1, ref index, typeInfo);
|
||
}
|
||
PopArray();
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
m_nestingLevel--;
|
||
}
|
||
}
|
||
|
||
private void CheckAndIncrementNestingLevel()
|
||
{
|
||
if (m_nestingLevel > m_context.MaxEncodingNestingLevels)
|
||
{
|
||
throw ServiceResultException.Create(2148007936u, "Maximum nesting level of {0} was exceeded", m_context.MaxEncodingNestingLevels);
|
||
}
|
||
m_nestingLevel++;
|
||
}
|
||
}
|
||
}
|