diff --git a/src/KeePassLib2Android/KeePassLib2Android.csproj b/src/KeePassLib2Android/KeePassLib2Android.csproj index d925d883..712720e4 100644 --- a/src/KeePassLib2Android/KeePassLib2Android.csproj +++ b/src/KeePassLib2Android/KeePassLib2Android.csproj @@ -47,6 +47,9 @@ SdkOnly + + ..\ProtoBuf\protobuf-net.dll + @@ -126,6 +129,7 @@ + diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs index 03456962..4eff0c4a 100644 --- a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs +++ b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs @@ -127,8 +127,34 @@ namespace KeePassLib.Serialization } else m_randomStream = null; // No random stream for plain-text files - ReadXmlStreamed(readerStream, hashedStream); - // ReadXmlDom(readerStream); + // Test: read to memory + var stopWatch = Stopwatch.StartNew(); + var memStream = new MemoryStream((int)hashedStream.Length); + CopyStream(readerStream, memStream); + readerStream.Close(); + readerStream = memStream; + System.Diagnostics.Debug.WriteLine(String.Format("Copy input stream: {0}ms", stopWatch.ElapsedMilliseconds)); + + var isXml = memStream.ReadByte() == '<'; + memStream.Seek(0, SeekOrigin.Begin); + + if (isXml) + { + stopWatch.Restart(); + + ReadXmlStreamed(readerStream, hashedStream); + System.Diagnostics.Debug.WriteLine(String.Format("ReadXmlStreamed: {0}ms", stopWatch.ElapsedMilliseconds)); + + } + else + { + stopWatch.Restart(); + + KdbpFile.ReadDocument(m_pwDatabase, readerStream, m_pbProtectedStreamKey, m_pbHashOfHeader); + + System.Diagnostics.Debug.WriteLine(String.Format("KdbpFile.ReadDocument: {0}ms", stopWatch.ElapsedMilliseconds)); + + } readerStream.Close(); // GC.KeepAlive(br); @@ -141,6 +167,17 @@ namespace KeePassLib.Serialization finally { CommonCleanUpRead(sSource, hashedStream); } } + public static void CopyStream(Stream input, Stream output) + { + byte[] buffer = new byte[4096]; + int read; + while ((read = input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer, 0, read); + } + output.Seek(0, SeekOrigin.Begin); + } + private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream) { hashedStream.Close(); diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs index 802feaf0..fbc31e6c 100644 --- a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs +++ b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs @@ -122,11 +122,16 @@ namespace KeePassLib.Serialization writerStream = hashedStream; else { Debug.Assert(false); throw new FormatException("KdbFormat"); } + /* m_xmlWriter = new XmlTextWriter(writerStream, encNoBom); WriteDocument(pgDataSource); m_xmlWriter.Flush(); m_xmlWriter.Close(); + */ + + KdbpFile.WriteDocument(m_pwDatabase, writerStream, m_pbProtectedStreamKey, m_pbHashOfHeader); + writerStream.Close(); } finally { CommonCleanUpWrite(sSaveTo, hashedStream); } diff --git a/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs b/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs new file mode 100644 index 00000000..326d391b --- /dev/null +++ b/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs @@ -0,0 +1,1425 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ProtoBuf; +using System.Drawing; +using KeePassLib.Collections; +using KeePassLib.Security; +using KeePassLib.Cryptography; +using System.IO; +using ProtoBuf.Meta; + +namespace KeePassLib.Serialization +{ + internal class KdbpFile + { + public static void WriteDocument(PwDatabase database, Stream stream, byte[] protectedStreamKey, byte[] hashOfHeader) + { + var context = new SerializationContext + { + Context = new BufferContext(database, + new CryptoRandomStream(CrsAlgorithm.Salsa20, protectedStreamKey), hashOfHeader) + }; + + RuntimeTypeModel.Default.Serialize(stream, new PwDatabaseBuffer(database), context); + } + + public static void ReadDocument(PwDatabase database, Stream stream, byte[] protectedStreamKey, byte[] expectedHashOfHeader) + { + + var context = new BufferContext(database, new CryptoRandomStream(CrsAlgorithm.Salsa20, protectedStreamKey)); + + // Deserialisation will occur into the database already in context. + RuntimeTypeModel.Default.Deserialize(stream, null, typeof(PwDatabaseBuffer), new SerializationContext { Context = context }); + + if (expectedHashOfHeader.Length > 0 && + !KeePassLib.Utility.MemUtil.ArraysEqual(context.HeaderHash, expectedHashOfHeader)) + { + throw new IOException(KeePassLib.Resources.KLRes.FileCorrupted); + } + } + + private class BufferContext + { + // ProtectedBinary objects may be referred to multipe times by entry histories, so reference them only once by ensuring a 1:1 mapping to the buffer wrapping them. + public readonly Dictionary BinaryPool = new Dictionary(); + + public readonly PwDatabase Database; + public readonly CryptoRandomStream RandomStream; + public byte[] HeaderHash; + + public BufferContext(PwDatabase database, CryptoRandomStream randomStream, byte[] pbHashOfHeader = null) + { + Database = database; + RandomStream = randomStream; + HeaderHash = pbHashOfHeader; + } + } + + [ProtoContract] + private class PwDatabaseBuffer + { + #region Serialization + + private PwDatabase mDatabase; + private PwDeletedObjectListBuffer mDeletedObjects; + private PwCustomIconListBuffer mCustomIcons; + + public PwDatabaseBuffer(PwDatabase database) + { + mDatabase = database; + mDeletedObjects = new PwDeletedObjectListBuffer(mDatabase.DeletedObjects); + mCustomIcons = new PwCustomIconListBuffer(mDatabase.CustomIcons); + } + + [ProtoBeforeSerialization] + private void BeforeSerialization(SerializationContext context) + { + var bufferContext = (BufferContext)context.Context; + + System.Diagnostics.Debug.Assert(mDatabase == bufferContext.Database); + + HeaderHash = bufferContext.HeaderHash; + } + #endregion + + #region Deserialization + private PwDatabaseBuffer() + { + } + + [ProtoBeforeDeserialization] + private void BeforeDeserialization(SerializationContext context) + { + var bufferContext = (BufferContext)context.Context; + + mDatabase = bufferContext.Database; + mDeletedObjects = new PwDeletedObjectListBuffer(mDatabase.DeletedObjects); + mCustomIcons = new PwCustomIconListBuffer(mDatabase.CustomIcons); + } + + [ProtoAfterDeserialization] + private void AfterDeserialization(SerializationContext context) + { + var bufferContext = (BufferContext)context.Context; + + bufferContext.HeaderHash = HeaderHash; + } + #endregion + + [ProtoMember(1)] + public string Generator + { + get { return PwDatabase.LocalizedAppName; } + set { /* Ignore */ } + } + + [ProtoMember(2, OverwriteList = true)] + public byte[] HeaderHash; + + [ProtoMember(3)] + public string Name + { + get { return mDatabase.Name; } + set { mDatabase.Name = value; } + } + + [ProtoMember(4)] + public DateTime NameChanged + { + get { return mDatabase.NameChanged; } + set { mDatabase.NameChanged = value; } + } + + [ProtoMember(5)] + public string Description + { + get { return mDatabase.Description; } + set { mDatabase.Description = value; } + } + + [ProtoMember(6)] + public DateTime DescriptionChanged + { + get { return mDatabase.DescriptionChanged; } + set { mDatabase.DescriptionChanged = value; } + } + + [ProtoMember(7)] + public string DefaultUserName + { + get { return mDatabase.DefaultUserName; } + set { mDatabase.DefaultUserName = value; } + } + + [ProtoMember(8)] + public DateTime DefaultUserNameChanged + { + get { return mDatabase.DefaultUserNameChanged; } + set { mDatabase.DefaultUserNameChanged = value; } + } + + [ProtoMember(9)] + public uint MaintenanceHistoryDays + { + get { return mDatabase.MaintenanceHistoryDays; } + set { mDatabase.MaintenanceHistoryDays = value; } + } + + [ProtoMember(10)] + public int Color + { + get { return mDatabase.Color.ToArgb(); } + set { mDatabase.Color = System.Drawing.Color.FromArgb(value); } + } + + [ProtoMember(11)] + public DateTime MasterKeyChanged + { + get { return mDatabase.MasterKeyChanged; } + set { mDatabase.MasterKeyChanged = value; } + } + + [ProtoMember(12)] + public long MasterKeyChangeRec + { + get { return mDatabase.MasterKeyChangeRec; } + set { mDatabase.MasterKeyChangeRec = value; } + } + + [ProtoMember(13)] + public long MasterKeyChangeForce + { + get { return mDatabase.MasterKeyChangeForce; } + set { mDatabase.MasterKeyChangeForce = value; } + } + + [ProtoMember(14)] + public MemoryProtectionConfigBuffer MemoryProtection + { + get { return new MemoryProtectionConfigBuffer(mDatabase.MemoryProtection); } + set { mDatabase.MemoryProtection = value.MemoryProtectionConfig; } + } + + [ProtoMember(15)] + public PwCustomIconListBuffer CustomIcons + { + get { return mCustomIcons; } + } + + [ProtoMember(16)] + public bool RecycleBinEnabled + { + get { return mDatabase.RecycleBinEnabled; } + set { mDatabase.RecycleBinEnabled = value; } + } + + [ProtoMember(17, OverwriteList = true)] + public byte[] RecycleBinUuid + { + get { return mDatabase.RecycleBinUuid.UuidBytes; } + set { mDatabase.RecycleBinUuid = new PwUuid(value); } + } + + [ProtoMember(18)] + public DateTime RecycleBinChanged + { + get { return mDatabase.RecycleBinChanged; } + set { mDatabase.RecycleBinChanged = value; } + } + + [ProtoMember(19, OverwriteList = true)] + public byte[] EntryTemplatesGroup + { + get { return mDatabase.EntryTemplatesGroup.UuidBytes; } + set { mDatabase.EntryTemplatesGroup = new PwUuid(value); } + } + + [ProtoMember(20)] + public DateTime EntryTemplatesGroupChanged + { + get { return mDatabase.EntryTemplatesGroupChanged; } + set { mDatabase.EntryTemplatesGroupChanged = value; } + } + + [ProtoMember(21)] + public int HistoryMaxItems + { + get { return mDatabase.HistoryMaxItems; } + set { mDatabase.HistoryMaxItems = value; } + } + + [ProtoMember(22)] + public long HistoryMaxSize + { + get { return mDatabase.HistoryMaxSize; } + set { mDatabase.HistoryMaxSize = value; } + } + + [ProtoMember(23, OverwriteList = true)] + public byte[] LastSelectedGroup + { + get { return mDatabase.LastSelectedGroup.UuidBytes; } + set { mDatabase.LastSelectedGroup = new PwUuid(value); } + } + + [ProtoMember(24, OverwriteList = true)] + public byte[] LastTopVisibleGroup + { + get { return mDatabase.LastTopVisibleGroup.UuidBytes; } + set { mDatabase.LastTopVisibleGroup = new PwUuid(value); } + } + + [ProtoMember(25)] + public StringDictionaryExBuffer CustomData + { + get { return new StringDictionaryExBuffer(mDatabase.CustomData); } + set { mDatabase.CustomData = value.StringDictionaryEx; } + } + + [ProtoMember(27)] + public PwGroupBuffer RootGroup + { + get { return new PwGroupBuffer(mDatabase.RootGroup); } + set { mDatabase.RootGroup = value.Group; } + } + + [ProtoMember(28)] + public PwDeletedObjectListBuffer DeletedObjects + { + get { return mDeletedObjects; } + } + } + + [ProtoContract] + private class StringDictionaryExBuffer : IEnumerable> + { + #region Serialization + private StringDictionaryEx mStringDictionaryEx; + + public StringDictionaryExBuffer(StringDictionaryEx stringDictionaryEx) + { + mStringDictionaryEx = stringDictionaryEx; + } + #endregion + + #region Deserialization + private StringDictionaryExBuffer() + { + mStringDictionaryEx = new StringDictionaryEx(); + } + + public StringDictionaryEx StringDictionaryEx { get { return mStringDictionaryEx; } } + + public void Add(KeyValuePair kvp) + { + mStringDictionaryEx.Set(kvp.Key, kvp.Value); + } + #endregion + + public IEnumerator> GetEnumerator() + { + return mStringDictionaryEx.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + [ProtoContract] + private class PwCustomIconListBuffer : IEnumerable + { + private List mCustomIcons; + #region Serialization + public PwCustomIconListBuffer(List customIcons) + { + mCustomIcons = customIcons; + } + #endregion + + #region Deserialization + public void Add(PwCustomIconBuffer item) + { + mCustomIcons.Add(item.CustomIcon); + } + #endregion + + public IEnumerator GetEnumerator() + { + foreach (var customIcon in mCustomIcons) + { + yield return new PwCustomIconBuffer(customIcon); + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + [ProtoContract] + private class PwCustomIconBuffer + { + #region Serialization + private PwCustomIcon mCustomIcon; + public PwCustomIconBuffer(PwCustomIcon CustomIcon) + { + mCustomIcon = CustomIcon; + Uuid = mCustomIcon.Uuid.UuidBytes; + ImageData = mCustomIcon.ImageDataPng; + } + #endregion + + #region Deserialization + private PwCustomIconBuffer() + { + } + + [ProtoAfterDeserialization] + private void AfterDeserialization(SerializationContext context) + { + mCustomIcon = new PwCustomIcon(new PwUuid(Uuid), ImageData); + } + + public PwCustomIcon CustomIcon { get { return mCustomIcon; } } + #endregion + + [ProtoMember(1, OverwriteList = true)] + public byte[] Uuid; + + [ProtoMember(2, OverwriteList = true)] + public byte[] ImageData; + } + + [ProtoContract] + private class MemoryProtectionConfigBuffer + { + #region Serialization + private readonly MemoryProtectionConfig mMemoryProtectionConfig; + + public MemoryProtectionConfigBuffer(MemoryProtectionConfig memoryProtectionConfig) + { + mMemoryProtectionConfig = memoryProtectionConfig; + } + #endregion + + #region Deserialization + private MemoryProtectionConfigBuffer() + { + mMemoryProtectionConfig = new MemoryProtectionConfig(); + } + + public MemoryProtectionConfig MemoryProtectionConfig { get { return mMemoryProtectionConfig; } } + #endregion + + [ProtoMember(1)] + public bool ProtectTitle + { + get { return mMemoryProtectionConfig.ProtectTitle; } + set { mMemoryProtectionConfig.ProtectTitle = value; } + } + + [ProtoMember(2)] + public bool ProtectUserName + { + get { return mMemoryProtectionConfig.ProtectUserName; } + set { mMemoryProtectionConfig.ProtectUserName = value; } + } + + [ProtoMember(3)] + public bool ProtectPassword + { + get { return mMemoryProtectionConfig.ProtectPassword; } + set { mMemoryProtectionConfig.ProtectPassword = value; } + } + + [ProtoMember(4)] + public bool ProtectUrl + { + get { return mMemoryProtectionConfig.ProtectUrl; } + set { mMemoryProtectionConfig.ProtectUrl = value; } + } + + [ProtoMember(5)] + public bool ProtectNotes + { + get { return mMemoryProtectionConfig.ProtectNotes; } + set { mMemoryProtectionConfig.ProtectNotes = value; } + } + } + + [ProtoContract] + private class PwDeletedObjectListBuffer : PwObjectListBufferBase + { + #region Serialization + public PwDeletedObjectListBuffer(PwObjectList objectList) + : base(objectList) + { + } + + protected override PwDeletedObjectBuffer CreateBuffer(PwDeletedObject item) + { + return new PwDeletedObjectBuffer(item); + } + #endregion + + #region Deserialization + private PwDeletedObjectListBuffer() + : base() + { + } + + public override void Add(PwDeletedObjectBuffer item) + { + ObjectList.Add(item.DeletedObject); + } + #endregion + } + + [ProtoContract] + private class PwDeletedObjectBuffer + { + #region Serialization + private readonly PwDeletedObject mDeletedObject; + + public PwDeletedObjectBuffer(PwDeletedObject deletedObject) + { + mDeletedObject = deletedObject; + } + #endregion + + #region Deserialization + private PwDeletedObjectBuffer() + { + mDeletedObject = new PwDeletedObject(); + } + + public PwDeletedObject DeletedObject { get { return mDeletedObject; } } + #endregion + + [ProtoMember(1, OverwriteList = true)] + public byte[] Uuid + { + get { return mDeletedObject.Uuid.UuidBytes; } + set { mDeletedObject.Uuid = new PwUuid(value); } + } + + [ProtoMember(2)] + public DateTime DeletionTime + { + get { return mDeletedObject.DeletionTime; } + set { mDeletedObject.DeletionTime = value; } + } + } + + [ProtoContract] + private class PwGroupBuffer + { + #region Serialization + private readonly PwGroup mGroup; + private readonly PwGroupEntryListBuffer mEntries; + private readonly PwGroupGroupListBuffer mGroups; + + public PwGroupBuffer(PwGroup group) + { + mGroup = group; + mEntries = new PwGroupEntryListBuffer(mGroup); + mGroups = new PwGroupGroupListBuffer(mGroup); + } + #endregion + + #region Deserialization + private PwGroupBuffer() + { + mGroup = new PwGroup(false, false); + mEntries = new PwGroupEntryListBuffer(mGroup); + mGroups = new PwGroupGroupListBuffer(mGroup); + } + + public PwGroup Group { get { return mGroup; } } + #endregion + + [ProtoMember(1, OverwriteList = true)] + public byte[] Uuid + { + get { return mGroup.Uuid.UuidBytes; } + set { mGroup.Uuid = new PwUuid(value); } + } + + [ProtoMember(2)] + public string Name + { + get { return mGroup.Name; } + set { mGroup.Name = value; } + } + + [ProtoMember(3)] + public string Notes + { + get { return mGroup.Notes; } + set { mGroup.Notes = value; } + } + + [ProtoMember(4)] + public PwIcon IconId + { + get { return mGroup.IconId; } + set { mGroup.IconId = value; } + } + + [ProtoMember(5, OverwriteList = true)] + public byte[] CustomIconUuid + { + get { return mGroup.CustomIconUuid.UuidBytes; } + set { mGroup.CustomIconUuid = new PwUuid(value); } + } + + [ProtoMember(6)] + public bool IsExpanded + { + get { return mGroup.IsExpanded; } + set { mGroup.IsExpanded = value; } + } + + [ProtoMember(7)] + public string DefaultAutoTypeSequence + { + get { return mGroup.DefaultAutoTypeSequence; } + set { mGroup.DefaultAutoTypeSequence = value; } + } + + [ProtoMember(8)] + public DateTime LastModificationTime + { + get { return mGroup.LastModificationTime; } + set { mGroup.LastModificationTime = value; } + } + + [ProtoMember(9)] + public DateTime CreationTime + { + get { return mGroup.CreationTime; } + set { mGroup.CreationTime = value; } + } + + [ProtoMember(10)] + public DateTime LastAccessTime + { + get { return mGroup.LastAccessTime; } + set { mGroup.LastAccessTime = value; } + } + + [ProtoMember(11)] + public DateTime ExpiryTime + { + get { return mGroup.ExpiryTime; } + set { mGroup.ExpiryTime = value; } + } + + [ProtoMember(12)] + public bool Expires + { + get { return mGroup.Expires; } + set { mGroup.Expires = value; } + } + + [ProtoMember(13)] + public ulong UsageCount + { + get { return mGroup.UsageCount; } + set { mGroup.UsageCount = value; } + } + + [ProtoMember(14)] + public DateTime LocationChanged + { + get { return mGroup.LocationChanged; } + set { mGroup.LocationChanged = value; } + } + + [ProtoMember(15)] + public bool? EnableAutoType + { + get { return mGroup.EnableAutoType; } + set { mGroup.EnableAutoType = value; } + } + + [ProtoMember(16)] + public bool? EnableSearching + { + get { return mGroup.EnableSearching; } + set { mGroup.EnableSearching = value; } + } + + [ProtoMember(17, OverwriteList = true)] + public byte[] LastTopVisibleEntry + { + get { return mGroup.LastTopVisibleEntry.UuidBytes; } + set { mGroup.LastTopVisibleEntry = new PwUuid(value); } + } + + [ProtoMember(18)] + public PwGroupGroupListBuffer Groups + { + get { return mGroups; } + } + + [ProtoMember(19)] + public PwGroupEntryListBuffer Entries + { + get { return mEntries; } + } + } + + private abstract class PwObjectListBufferBase : IEnumerable + where TData : class, KeePassLib.Interfaces.IDeepCloneable + { + #region Serialization + private PwObjectList mObjectList; + + protected PwObjectListBufferBase(PwObjectList objectList) + { + mObjectList = objectList; + } + + protected abstract TDataBuffer CreateBuffer(TData item); + #endregion + + #region Deserialization + protected PwObjectListBufferBase() + { + mObjectList = new PwObjectList(); + } + + public PwObjectList ObjectList { get { return mObjectList; } } + + public abstract void Add(TDataBuffer item); + #endregion + + public IEnumerator GetEnumerator() + { + foreach (var item in mObjectList) + { + yield return CreateBuffer(item); + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + [ProtoContract] + private class PwGroupGroupListBuffer : PwObjectListBufferBase + { + #region Serialization + private PwGroup mGroup; + public PwGroupGroupListBuffer(PwGroup group) + : base(group.Groups) + { + mGroup = group; + } + + protected override PwGroupBuffer CreateBuffer(PwGroup item) + { + return new PwGroupBuffer(item); + } + #endregion + + #region Deserialization + public override void Add(PwGroupBuffer item) + { + mGroup.AddGroup(item.Group, true); + } + #endregion + } + + [ProtoContract] + private class PwGroupEntryListBuffer : PwObjectListBufferBase + { + #region Serialization + private PwGroup mGroup; + public PwGroupEntryListBuffer(PwGroup group) + : base(group.Entries) + { + mGroup = group; + } + + protected override PwEntryBuffer CreateBuffer(PwEntry item) + { + return new PwEntryBuffer(item); + } + #endregion + + #region Deserialization + public override void Add(PwEntryBuffer item) + { + mGroup.AddEntry(item.Entry, true); + } + #endregion + } + + [ProtoContract] + private class PwEntryListBuffer : PwObjectListBufferBase + { + #region Serialization + public PwEntryListBuffer(PwObjectList entryList) + : base(entryList) + { + } + + protected override PwEntryBuffer CreateBuffer(PwEntry item) + { + return new PwEntryBuffer(item); + } + #endregion + + #region Deserialization + private PwEntryListBuffer() + : base() + { + } + + public override void Add(PwEntryBuffer item) + { + ObjectList.Add(item.Entry); + } + #endregion + } + + [ProtoContract] + private class PwEntryBuffer + { + #region Serialization + private readonly PwEntry mEntry; + private ProtectedStandardFieldDictionaryBuffer mEntryStandardStrings; + private ProtectedCustomFieldDictionaryBuffer mEntryCustomStrings; + private NamedProtectedBinaryListBuffer mEntryBinaries; + + public PwEntryBuffer(PwEntry entry) + { + mEntry = entry; + } + + [ProtoBeforeSerialization] + private void BeforeSerialization(SerializationContext context) + { + var bufferContext = (BufferContext)context.Context; + + // ProtectedStringDictionaryBuffer nver gets its own ProtoBeforeSerialization called as it's a list of objects rather than an object itself + List> customFields; + mEntryStandardStrings = new ProtectedStandardFieldDictionaryBuffer(mEntry.Strings, (int)mEntry.Strings.UCount, bufferContext, out customFields); + mEntryCustomStrings = new ProtectedCustomFieldDictionaryBuffer(customFields); + mEntryBinaries = new NamedProtectedBinaryListBuffer(mEntry.Binaries, (int)mEntry.Binaries.UCount, bufferContext); + } + #endregion + + #region Deserialization + private PwEntryBuffer() + { + mEntry = new PwEntry(false, false); + mEntryStandardStrings = new ProtectedStandardFieldDictionaryBuffer(mEntry.Strings); + mEntryCustomStrings = new ProtectedCustomFieldDictionaryBuffer(mEntry.Strings); + mEntryBinaries = new NamedProtectedBinaryListBuffer(mEntry.Binaries); + } + + public PwEntry Entry { get { return mEntry; } } + #endregion + + [ProtoMember(1, OverwriteList = true)] + public byte[] Uuid + { + get { return mEntry.Uuid.UuidBytes; } + set { mEntry.SetUuid(new PwUuid(value), false); } + } + + [ProtoMember(2)] + public PwIcon IconId + { + get { return mEntry.IconId; } + set { mEntry.IconId = value; } + } + + [ProtoMember(3, OverwriteList = true)] + public byte[] CustomIconUuid + { + get { return mEntry.CustomIconUuid.UuidBytes; } + set { mEntry.CustomIconUuid = new PwUuid(value); } + } + + [ProtoMember(4)] + public int ForegroundColor + { + get { return mEntry.ForegroundColor.ToArgb(); } + set { mEntry.ForegroundColor = Color.FromArgb(value); } + } + + [ProtoMember(5)] + public int BackgroundColor + { + get { return mEntry.BackgroundColor.ToArgb(); } + set { mEntry.BackgroundColor = Color.FromArgb(value); } + } + + [ProtoMember(6)] + public string OverrideUrl + { + get { return mEntry.OverrideUrl; } + set { mEntry.OverrideUrl = value; } + } + + [ProtoMember(7)] + public IList Tags + { + get { return mEntry.Tags; } + } + + [ProtoMember(8)] + public DateTime LastModificationTime + { + get { return mEntry.LastModificationTime; } + set { mEntry.LastModificationTime = value; } + } + + [ProtoMember(9)] + public DateTime CreationTime + { + get { return mEntry.CreationTime; } + set { mEntry.CreationTime = value; } + } + + [ProtoMember(10)] + public DateTime LastAccessTime + { + get { return mEntry.LastAccessTime; } + set { mEntry.LastAccessTime = value; } + } + + [ProtoMember(11)] + public DateTime ExpiryTime + { + get { return mEntry.ExpiryTime; } + set { mEntry.ExpiryTime = value; } + } + + [ProtoMember(12)] + public bool Expires + { + get { return mEntry.Expires; } + set { mEntry.Expires = value; } + } + + [ProtoMember(13)] + public ulong UsageCount + { + get { return mEntry.UsageCount; } + set { mEntry.UsageCount = value; } + } + + [ProtoMember(14)] + public DateTime LocationChanged + { + get { return mEntry.LocationChanged; } + set { mEntry.LocationChanged = value; } + } + + [ProtoMember(15)] + public ProtectedStandardFieldDictionaryBuffer StandardStrings + { + get { return mEntryStandardStrings; } + } + + [ProtoMember(16)] + public ProtectedCustomFieldDictionaryBuffer CustomStrings + { + get { return mEntryCustomStrings; } + } + + [ProtoMember(17, AsReference = true)] + public NamedProtectedBinaryListBuffer Binaries + { + get { return mEntryBinaries; } + } + + [ProtoMember(18)] + public AutoTypeConfigBuffer AutoType + { + get { return new AutoTypeConfigBuffer(mEntry.AutoType); } + set { mEntry.AutoType = value.AutoTypeConfig; } + } + + [ProtoMember(19)] + public PwEntryListBuffer History + { + get { return new PwEntryListBuffer(mEntry.History); } + set { mEntry.History = value.ObjectList; } + } + + } + + private abstract class ProtectedStringDictionaryBuffer : IEnumerable> + { + #region Serialization + private List> mProtectedStringBuffers; + + /// + /// Serialisation constructor. Reads strings from dictionary, does not write to it + /// + protected ProtectedStringDictionaryBuffer(int capacity) + { + mProtectedStringBuffers = new List>(capacity); + } + + protected void AddStringField(TKey key, ProtectedString value, bool? overrideProtect) + { + mProtectedStringBuffers.Add(new KeyValuePair(key, new ProtectedStringBuffer(value, overrideProtect))); + } + + public IEnumerator> GetEnumerator() + { + return mProtectedStringBuffers.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion + + #region Deserialization + private readonly ProtectedStringDictionary mDictionary; + + /// + /// Deerialisation constructor. Writes strings to dictionary, does read from it + /// + protected ProtectedStringDictionaryBuffer(ProtectedStringDictionary dictionary) + { + mDictionary = dictionary; + } + + public void Add(KeyValuePair item) + { + mDictionary.Set(GetFieldName(item.Key), item.Value.ProtectedString); + } + + protected abstract string GetFieldName(TKey key); + + #endregion + } + + [ProtoContract] + private class ProtectedCustomFieldDictionaryBuffer : ProtectedStringDictionaryBuffer + { + public ProtectedCustomFieldDictionaryBuffer(List> entryStrings) + : base(entryStrings.Count) + { + foreach (var kvp in entryStrings) + { + System.Diagnostics.Debug.Assert(!PwDefs.IsStandardField(kvp.Key)); + AddStringField(kvp.Key, kvp.Value, null); + } + } + + public ProtectedCustomFieldDictionaryBuffer(ProtectedStringDictionary dictionary) + : base(dictionary) + { } + + protected override string GetFieldName(string key) + { + return key; + } + } + + [ProtoContract] + private class ProtectedStandardFieldDictionaryBuffer : ProtectedStringDictionaryBuffer + { + public enum StandardField + { + Title, + UserName, + Password, + Url, + Notes + } + + public ProtectedStandardFieldDictionaryBuffer(IEnumerable> entryStrings, int entryStringCount, BufferContext context, + out List> customFields) // Perf optimisation - return the custom fields so we don't have to determine them again + : base(entryStringCount) + { + customFields = new List>(entryStringCount); + + var database = context.Database; + + foreach (var kvp in entryStrings) + { + var field = GetField(kvp.Key); + + if (field.HasValue) + { + // Logic from KdbxFile.Write + + bool? overrideProtect = null; + // Adjust memory protection setting (which might be different + // from the database default, e.g. due to an import which + // didn't specify the correct setting) + switch (field.Value) + { + case StandardField.Title: + overrideProtect = database.MemoryProtection.ProtectTitle; + break; + case StandardField.UserName: + overrideProtect = database.MemoryProtection.ProtectUserName; + break; + case StandardField.Password: + overrideProtect = database.MemoryProtection.ProtectPassword; + break; + case StandardField.Url: + overrideProtect = database.MemoryProtection.ProtectUrl; + break; + case StandardField.Notes: + overrideProtect = database.MemoryProtection.ProtectNotes; + break; + } + + AddStringField(field.Value, kvp.Value, overrideProtect); + } + else + { + customFields.Add(kvp); + } + } + } + + private static StandardField? GetField(string fieldName) + { + switch (fieldName) + { + case PwDefs.TitleField: + return StandardField.Title; + case PwDefs.UserNameField: + return StandardField.UserName; + case PwDefs.PasswordField: + return StandardField.Password; + case PwDefs.UrlField: + return StandardField.Url; + case PwDefs.NotesField: + return StandardField.Notes; + + default: + System.Diagnostics.Debug.Assert(!PwDefs.IsStandardField(fieldName)); + return null; + } + } + + public ProtectedStandardFieldDictionaryBuffer(ProtectedStringDictionary dictionary) + : base(dictionary) + { } + + protected override string GetFieldName(StandardField key) + { + switch (key) + { + case StandardField.Title: + return PwDefs.TitleField; + case StandardField.UserName: + return PwDefs.UserNameField; + case StandardField.Password: + return PwDefs.PasswordField; + case StandardField.Url: + return PwDefs.UrlField; + case StandardField.Notes: + return PwDefs.NotesField; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + [ProtoContract] + private class ProtectedStringBuffer + { + #region Serialisation + private ProtectedString mProtectedString; + + public ProtectedStringBuffer(ProtectedString protectedString, bool? overrideProtect) + { + mProtectedString = protectedString; + IsProtected = overrideProtect.GetValueOrDefault(mProtectedString.IsProtected); + } + + [ProtoBeforeSerialization] + private void BeforeSerialization(SerializationContext context) + { + if (IsProtected) + { + Value = mProtectedString.ReadXorredString(((BufferContext)context.Context).RandomStream); + } + else + { + Value = mProtectedString.ReadUtf8(); + } + } + #endregion + + #region Deserialisation + private ProtectedStringBuffer() + { + } + + [ProtoAfterDeserialization] + private void AfterDeserialization(SerializationContext context) + { + if (IsProtected) + { + byte[] pbPad = ((BufferContext)context.Context).RandomStream.GetRandomBytes((uint)Value.Length); + mProtectedString = new ProtectedString(IsProtected, new XorredBuffer(Value, pbPad)); + } + else + { + mProtectedString = new ProtectedString(IsProtected, Value); + } + } + + public ProtectedString ProtectedString { get { return mProtectedString; } } + + #endregion + + [ProtoMember(1)] + public bool IsProtected; + + [ProtoMember(2, OverwriteList = true)] + public byte[] Value; + } + + [ProtoContract] + private class NamedProtectedBinaryListBuffer : IEnumerable + { + #region Serialisation + private readonly List mNamedBinaries; + + public NamedProtectedBinaryListBuffer(IEnumerable> binaries, int binariesCount, BufferContext context) + { + mNamedBinaries = new List(binariesCount); + foreach (var kvp in binaries) + { + NamedProtectedBinaryBuffer namedProtectedBinaryBuffer; + if (!context.BinaryPool.TryGetValue(kvp.Value, out namedProtectedBinaryBuffer)) + { + // Hasn't been put in the pool yet, so create it + namedProtectedBinaryBuffer = new NamedProtectedBinaryBuffer(kvp); + context.BinaryPool.Add(kvp.Value, namedProtectedBinaryBuffer); + } + mNamedBinaries.Add(namedProtectedBinaryBuffer); + } + } + + public IEnumerator GetEnumerator() + { + return mNamedBinaries.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion + + #region Deserialization + private readonly ProtectedBinaryDictionary mBinaryDictionary; + + public NamedProtectedBinaryListBuffer(ProtectedBinaryDictionary binaryDictionary) + { + mBinaryDictionary = binaryDictionary; + } + + public void Add(NamedProtectedBinaryBuffer item) + { + mBinaryDictionary.Set(item.Name, item.ProtectedBinary); + } + #endregion + } + + [ProtoContract] + private class NamedProtectedBinaryBuffer + { + #region Serialization + private ProtectedBinary mProtectedBinary; + public NamedProtectedBinaryBuffer(KeyValuePair namedBinary) + { + Name = namedBinary.Key; + mProtectedBinary = namedBinary.Value; + IsProtected = mProtectedBinary.IsProtected; + } + + [ProtoBeforeSerialization] + private void BeforeSerialization(SerializationContext context) + { + if (IsProtected) + { + Value = mProtectedBinary.ReadXorredData(((BufferContext)context.Context).RandomStream); + } + else + { + Value = mProtectedBinary.ReadData(); + } + } + #endregion + + #region Deserialisation + private NamedProtectedBinaryBuffer() + { + } + + [ProtoAfterDeserialization] + private void AfterDeserialization(SerializationContext context) + { + if (IsProtected) + { + byte[] pbPad = ((BufferContext)context.Context).RandomStream.GetRandomBytes((uint)Value.Length); + mProtectedBinary = new ProtectedBinary(IsProtected, new XorredBuffer(Value, pbPad)); + } + else + { + mProtectedBinary = new ProtectedBinary(IsProtected, Value); + } + } + + public ProtectedBinary ProtectedBinary { get { return mProtectedBinary; } } + + #endregion + + [ProtoMember(1)] + public string Name; + + [ProtoMember(2)] + public bool IsProtected; + + [ProtoMember(3, OverwriteList = true)] + public byte[] Value; + } + + [ProtoContract] + private class AutoTypeConfigBuffer + { + private readonly AutoTypeAssociationsBuffer mAutoTypeAssociationsBuffer; + #region Serialization + private AutoTypeConfig mAutoTypeConfig; + public AutoTypeConfigBuffer(AutoTypeConfig autoTypeConfig) + { + mAutoTypeConfig = autoTypeConfig; + mAutoTypeAssociationsBuffer = new AutoTypeAssociationsBuffer(mAutoTypeConfig); + } + #endregion + + #region Deserialization + private AutoTypeConfigBuffer() + { + mAutoTypeConfig = new AutoTypeConfig(); + mAutoTypeAssociationsBuffer = new AutoTypeAssociationsBuffer(mAutoTypeConfig); + } + + public AutoTypeConfig AutoTypeConfig { get { return mAutoTypeConfig; } } + #endregion + + [ProtoMember(1)] + public bool Enabled + { + get { return mAutoTypeConfig.Enabled; } + set { mAutoTypeConfig.Enabled = value; } + } + + [ProtoMember(2)] + public AutoTypeObfuscationOptions ObfuscationOptions + { + get { return mAutoTypeConfig.ObfuscationOptions; } + set { mAutoTypeConfig.ObfuscationOptions = value; } + } + + [ProtoMember(3)] + public string DefaultSequence + { + get { return mAutoTypeConfig.DefaultSequence; } + set { mAutoTypeConfig.DefaultSequence = value; } + } + + [ProtoMember(4)] + public AutoTypeAssociationsBuffer Associations + { + get { return mAutoTypeAssociationsBuffer; } + } + } + + [ProtoContract] + private class AutoTypeAssociationsBuffer : IEnumerable + { + #region Serialization + private AutoTypeConfig mAutoTypeConfig; + + public AutoTypeAssociationsBuffer(AutoTypeConfig autoTypeConfig) + { + mAutoTypeConfig = autoTypeConfig; + } + + public IEnumerator GetEnumerator() + { + foreach (var autoTypeAssociation in mAutoTypeConfig.Associations) + { + yield return new AutoTypeAssociationBuffer(autoTypeAssociation); + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion + + #region Deserialization + public void Add(AutoTypeAssociationBuffer value) + { + mAutoTypeConfig.Add(value.AutoTypeAssociation); + } + #endregion + } + + [ProtoContract] + private class AutoTypeAssociationBuffer + { + #region Serialization + private AutoTypeAssociation mAutoTypeAssociation; + + public AutoTypeAssociationBuffer(AutoTypeAssociation autoTypeAssociation) + { + mAutoTypeAssociation = autoTypeAssociation; + } + #endregion + + #region Deserialization + private AutoTypeAssociationBuffer() + { + mAutoTypeAssociation = new AutoTypeAssociation(); + } + + public AutoTypeAssociation AutoTypeAssociation { get { return mAutoTypeAssociation; } } + #endregion + + [ProtoMember(1)] + public string WindowName + { + get { return mAutoTypeAssociation.WindowName; } + set { mAutoTypeAssociation.WindowName = value; } + } + + [ProtoMember(2)] + public string Sequence + { + get { return mAutoTypeAssociation.Sequence; } + set { mAutoTypeAssociation.Sequence = value; } + } + } + } +} diff --git a/src/ProtoBuf/protobuf-net.dll b/src/ProtoBuf/protobuf-net.dll new file mode 100644 index 00000000..adc83a91 Binary files /dev/null and b/src/ProtoBuf/protobuf-net.dll differ diff --git a/src/ProtoBuf/protobuf-net.pdb b/src/ProtoBuf/protobuf-net.pdb new file mode 100644 index 00000000..838b0bbe Binary files /dev/null and b/src/ProtoBuf/protobuf-net.pdb differ diff --git a/src/ProtoBuf/protobuf-net.xml b/src/ProtoBuf/protobuf-net.xml new file mode 100644 index 00000000..3451e38c --- /dev/null +++ b/src/ProtoBuf/protobuf-net.xml @@ -0,0 +1,2747 @@ + + + + protobuf-net + + + + + Provides support for common .NET types that do not have a direct representation + in protobuf, using the definitions from bcl.proto + + + + + Creates a new instance of the specified type, bypassing the constructor. + + The type to create + The new instance + If the platform does not support constructor-skipping + + + + Writes a TimeSpan to a protobuf stream + + + + + Parses a TimeSpan from a protobuf stream + + + + + Parses a DateTime from a protobuf stream + + + + + Writes a DateTime to a protobuf stream + + + + + Parses a decimal from a protobuf stream + + + + + Writes a decimal to a protobuf stream + + + + + Writes a Guid to a protobuf stream + + + + + Parses a Guid from a protobuf stream + + + + + Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. + + + + + Writes an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. + + + + + Optional behaviours that introduce .NET-specific functionality + + + + + No special behaviour + + + + + Enables full object-tracking/full-graph support. + + + + + Embeds the type information into the stream, allowing usage with types not known in advance. + + + + + If false, the constructor for the type is bypassed during deserialization, meaning any field initializers + or other initialization code is skipped. + + + + + Should the object index be reserved, rather than creating an object promptly + + + + + Provides a simple buffer-based implementation of an extension object. + + + + + Provides addition capability for supporting unexpected fields during + protocol-buffer serialization/deserialization. This allows for loss-less + round-trip/merge, even when the data is not fully understood. + + + + + Requests a stream into which any unexpected fields can be persisted. + + A new stream suitable for storing data. + + + + Indicates that all unexpected fields have now been stored. The + implementing class is responsible for closing the stream. If + "commit" is not true the data may be discarded. + + The stream originally obtained by BeginAppend. + True if the append operation completed successfully. + + + + Requests a stream of the unexpected fields previously stored. + + A prepared stream of the unexpected fields. + + + + Indicates that all unexpected fields have now been read. The + implementing class is responsible for closing the stream. + + The stream originally obtained by BeginQuery. + + + + Requests the length of the raw binary stream; this is used + when serializing sub-entities to indicate the expected size. + + The length of the binary stream representing unexpected data. + + + Specifies a method on the root-contract in an hierarchy to be invoked before serialization. + + + Specifies a method on the root-contract in an hierarchy to be invoked after serialization. + + + Specifies a method on the root-contract in an hierarchy to be invoked before deserialization. + + + Specifies a method on the root-contract in an hierarchy to be invoked after deserialization. + + + + Pushes a null reference onto the stack. Note that this should only + be used to return a null (or set a variable to null); for null-tests + use BranchIfTrue / BranchIfFalse. + + + + + Creates a new "using" block (equivalent) around a variable; + the variable must exist, and note that (unlike in C#) it is + the variables *final* value that gets disposed. If you need + *original* disposal, copy your variable first. + + It is the callers responsibility to ensure that the variable's + scope fully-encapsulates the "using"; if not, the variable + may be re-used (and thus re-assigned) unexpectedly. + + + + + Sub-format to use when serializing/deserializing data + + + + + Uses the default encoding for the data-type. + + + + + When applied to signed integer-based data (including Decimal), this + indicates that zigzag variant encoding will be used. This means that values + with small magnitude (regardless of sign) take a small amount + of space to encode. + + + + + When applied to signed integer-based data (including Decimal), this + indicates that two's-complement variant encoding will be used. + This means that any -ve number will take 10 bytes (even for 32-bit), + so should only be used for compatibility. + + + + + When applied to signed integer-based data (including Decimal), this + indicates that a fixed amount of space will be used. + + + + + When applied to a sub-message, indicates that the value should be treated + as group-delimited. + + + + + Simple base class for supporting unexpected fields allowing + for loss-less round-tips/merge, even if the data is not understod. + The additional fields are (by default) stored in-memory in a buffer. + + As an example of an alternative implementation, you might + choose to use the file system (temporary files) as the back-end, tracking + only the paths [such an object would ideally be IDisposable and use + a finalizer to ensure that the files are removed]. + + + + + Indicates that the implementing type has support for protocol-buffer + extensions. + + Can be implemented by deriving from Extensible. + + + + Retrieves the extension object for the current + instance, optionally creating it if it does not already exist. + + Should a new extension object be + created if it does not already exist? + The extension object if it exists (or was created), or null + if the extension object does not exist or is not available. + The createIfMissing argument is false during serialization, + and true during deserialization upon encountering unexpected fields. + + + + Retrieves the extension object for the current + instance, optionally creating it if it does not already exist. + + Should a new extension object be + created if it does not already exist? + The extension object if it exists (or was created), or null + if the extension object does not exist or is not available. + The createIfMissing argument is false during serialization, + and true during deserialization upon encountering unexpected fields. + + + + Provides a simple, default implementation for extension support, + optionally creating it if it does not already exist. Designed to be called by + classes implementing . + + Should a new extension object be + created if it does not already exist? + The extension field to check (and possibly update). + The extension object if it exists (or was created), or null + if the extension object does not exist or is not available. + The createIfMissing argument is false during serialization, + and true during deserialization upon encountering unexpected fields. + + + + Appends the value as an additional (unexpected) data-field for the instance. + Note that for non-repeated sub-objects, this equates to a merge operation; + for repeated sub-objects this adds a new instance to the set; for simple + values the new value supercedes the old value. + + Note that appending a value does not remove the old value from + the stream; avoid repeatedly appending values for the same field. + The type of the value to append. + The extensible object to append the value to. + The field identifier; the tag should not be defined as a known data-field for the instance. + The value to append. + + + + Appends the value as an additional (unexpected) data-field for the instance. + Note that for non-repeated sub-objects, this equates to a merge operation; + for repeated sub-objects this adds a new instance to the set; for simple + values the new value supercedes the old value. + + Note that appending a value does not remove the old value from + the stream; avoid repeatedly appending values for the same field. + The data-type of the field. + The data-format to use when encoding the value. + The extensible object to append the value to. + The field identifier; the tag should not be defined as a known data-field for the instance. + The value to append. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned is the composed value after merging any duplicated content; if the + value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The effective value of the field, or the default value if not found. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned is the composed value after merging any duplicated content; if the + value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + The effective value of the field, or the default value if not found. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned (in "value") is the composed value after merging any duplicated content; + if the value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The effective value of the field, or the default value if not found. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + True if data for the field was present, false otherwise. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned (in "value") is the composed value after merging any duplicated content; + if the value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The effective value of the field, or the default value if not found. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + True if data for the field was present, false otherwise. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned (in "value") is the composed value after merging any duplicated content; + if the value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The effective value of the field, or the default value if not found. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + Allow tags that are present as part of the definition; for example, to query unknown enum values. + True if data for the field was present, false otherwise. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + Each occurrence of the field is yielded separately, making this usage suitable for "repeated" + (list) fields. + + The extended data is processed lazily as the enumerator is iterated. + The data-type of the field. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + An enumerator that yields each occurrence of the field. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + Each occurrence of the field is yielded separately, making this usage suitable for "repeated" + (list) fields. + + The extended data is processed lazily as the enumerator is iterated. + The data-type of the field. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + An enumerator that yields each occurrence of the field. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + The value returned (in "value") is the composed value after merging any duplicated content; + if the value is "repeated" (a list), then use GetValues instead. + + The data-type of the field. + The model to use for configuration. + The effective value of the field, or the default value if not found. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + Allow tags that are present as part of the definition; for example, to query unknown enum values. + True if data for the field was present, false otherwise. + + + + Queries an extensible object for an additional (unexpected) data-field for the instance. + Each occurrence of the field is yielded separately, making this usage suitable for "repeated" + (list) fields. + + The extended data is processed lazily as the enumerator is iterated. + The model to use for configuration. + The data-type of the field. + The extensible object to obtain the value from. + The field identifier; the tag should not be defined as a known data-field for the instance. + The data-format to use when decoding the value. + An enumerator that yields each occurrence of the field. + + + + Appends the value as an additional (unexpected) data-field for the instance. + Note that for non-repeated sub-objects, this equates to a merge operation; + for repeated sub-objects this adds a new instance to the set; for simple + values the new value supercedes the old value. + + Note that appending a value does not remove the old value from + the stream; avoid repeatedly appending values for the same field. + The model to use for configuration. + The data-format to use when encoding the value. + The extensible object to append the value to. + The field identifier; the tag should not be defined as a known data-field for the instance. + The value to append. + + + + This class acts as an internal wrapper allowing us to do a dynamic + methodinfo invoke; an't put into Serializer as don't want on public + API; can't put into Serializer<T> since we need to invoke + accross classes, which isn't allowed in Silverlight) + + + + + All this does is call GetExtendedValuesTyped with the correct type for "instance"; + this ensures that we don't get issues with subclasses declaring conflicting types - + the caller must respect the fields defined for the type they pass in. + + + + + All this does is call GetExtendedValuesTyped with the correct type for "instance"; + this ensures that we don't get issues with subclasses declaring conflicting types - + the caller must respect the fields defined for the type they pass in. + + + + + Not all frameworks are created equal (fx1.1 vs fx2.0, + micro-framework, compact-framework, + silverlight, etc). This class simply wraps up a few things that would + otherwise make the real code unnecessarily messy, providing fallback + implementations if necessary. + + + + + Intended to be a direct map to regular TypeCode, but: + - with missing types + - existing on WinRT + + + + + Specifies the method used to infer field tags for members of the type + under consideration. Tags are deduced using the invariant alphabetic + sequence of the members' names; this makes implicit field tags very brittle, + and susceptible to changes such as field names (normally an isolated + change). + + + + + No members are serialized implicitly; all members require a suitable + attribute such as [ProtoMember]. This is the recmomended mode for + most scenarios. + + + + + Public properties and fields are eligible for implicit serialization; + this treats the public API as a contract. Ordering beings from ImplicitFirstTag. + + + + + Public and non-public fields are eligible for implicit serialization; + this acts as a state/implementation serializer. Ordering beings from ImplicitFirstTag. + + + + + Represents the set of serialization callbacks to be used when serializing/deserializing a type. + + + + Called before serializing an instance + + + Called before deserializing an instance + + + Called after serializing an instance + + + Called after deserializing an instance + + + + True if any callback is set, else False + + + + + Represents a type at runtime for use with protobuf, allowing the field mappings (etc) to be defined + + + + + Get the name of the type being represented + + + + + Adds a known sub-type to the inheritance model + + + + + Adds a known sub-type to the inheritance model + + + + + Assigns the callbacks to use during serialiation/deserialization. + + The method (or null) called before serialization begins. + The method (or null) called when serialization is complete. + The method (or null) called before deserialization begins (or when a new instance is created during deserialization). + The method (or null) called when deserialization is complete. + The set of callbacks. + + + + Assigns the callbacks to use during serialiation/deserialization. + + The name of the method (or null) called before serialization begins. + The name of the method (or null) called when serialization is complete. + The name of the method (or null) called before deserialization begins (or when a new instance is created during deserialization). + The name of the method (or null) called when deserialization is complete. + The set of callbacks. + + + + Designate a factory-method to use to create instances of this type + + + + + Designate a factory-method to use to create instances of this type + + + + + Throws an exception if the type has been made immutable + + + + + Adds a member (by name) to the MetaType + + + + + Adds a member (by name) to the MetaType, returning the ValueMember rather than the fluent API. + This is otherwise identical to Add. + + + + + Adds a member (by name) to the MetaType + + + + + Performs serialization of this type via a surrogate; all + other serialization options are ignored and handled + by the surrogate's configuration. + + + + + Adds a set of members (by name) to the MetaType + + + + + Adds a member (by name) to the MetaType + + + + + Adds a member (by name) to the MetaType, including an itemType and defaultType for representing lists + + + + + Adds a member (by name) to the MetaType, including an itemType and defaultType for representing lists, returning the ValueMember rather than the fluent API. + This is otherwise identical to Add. + + + + + Returns the ValueMember instances associated with this type + + + + + Returns the SubType instances associated with this type + + + + + Compiles the serializer for this type; this is *not* a full + standalone compile, but can significantly boost performance + while allowing additional types to be added. + + An in-place compile can access non-public types / members + + + + Gets the base-type for this type + + + + + When used to compile a model, should public serialization/deserialzation methods + be included for this type? + + + + + Should this type be treated as a reference by default? + + + + + Indicates whether the current type has defined callbacks + + + + + Indicates whether the current type has defined subtypes + + + + + Returns the set of callbacks defined for this type + + + + + Gets or sets the name of this contract. + + + + + The runtime type that the meta-type represents + + + + + Gets or sets whether the type should use a parameterless constructor (the default), + or whether the type should skip the constructor completely. This option is not supported + on compact-framework. + + + + + The concrete type to create when a new instance of this type is needed; this may be useful when dealing + with dynamic proxies, or with interface-based APIs + + + + + Returns the ValueMember that matchs a given field number, or null if not found + + + + + Returns the ValueMember that matchs a given member (property/field), or null if not found + + + + + Gets or sets a value indicating that an enum should be treated directly as an int/short/etc, rather + than enforcing .proto enum rules. This is useful *in particul* for [Flags] enums. + + + + + Gets or sets a value indicating that this type should NOT be treated as a list, even if it has + familiar list-like characteristics (enumerable, add, etc) + + + + + Provides protobuf serialization support for a number of types that can be defined at runtime + + + + + Provides protobuf serialization support for a number of types + + + + + Resolve a System.Type to the compiler-specific type + + + + + Resolve a System.Type to the compiler-specific type + + + + + This is the more "complete" version of Serialize, which handles single instances of mapped types. + The value is written as a complete field, including field-header and (for sub-objects) a + length-prefix + In addition to that, this provides support for: + - basic values; individual int / string / Guid / etc + - IEnumerable sequences of any type handled by TrySerializeAuxiliaryType + + + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + The existing instance to be serialized (cannot be null). + The destination stream to write to. + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + The existing instance to be serialized (cannot be null). + The destination stream to write to. + Additional information about this serialization operation. + + + + Writes a protocol-buffer representation of the given instance to the supplied writer. + + The existing instance to be serialized (cannot be null). + The destination writer to write to. + + + + Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed + data - useful with network IO. + + The type being merged. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + How to encode the length prefix. + The tag used as a prefix to each record (only used with base-128 style prefixes). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed + data - useful with network IO. + + The type being merged. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + How to encode the length prefix. + The tag used as a prefix to each record (only used with base-128 style prefixes). + Used to resolve types on a per-field basis. + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed + data - useful with network IO. + + The type being merged. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + How to encode the length prefix. + The tag used as a prefix to each record (only used with base-128 style prefixes). + Used to resolve types on a per-field basis. + Returns the number of bytes consumed by this operation (includes length-prefix overheads and any skipped data). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Reads a sequence of consecutive length-prefixed items from a stream, using + either base-128 or fixed-length prefixes. Base-128 prefixes with a tag + are directly comparable to serializing multiple items in succession + (use the tag to emulate the implicit behavior + when serializing a list/array). When a tag is + specified, any records with different tags are silently omitted. The + tag is ignored. The tag is ignores for fixed-length prefixes. + + The binary stream containing the serialized records. + The prefix style used in the data. + The tag of records to return (if non-positive, then no tag is + expected and all records are returned). + On a field-by-field basis, the type of object to deserialize (can be null if "type" is specified). + The type of object to deserialize (can be null if "resolver" is specified). + The sequence of deserialized objects. + + + + Reads a sequence of consecutive length-prefixed items from a stream, using + either base-128 or fixed-length prefixes. Base-128 prefixes with a tag + are directly comparable to serializing multiple items in succession + (use the tag to emulate the implicit behavior + when serializing a list/array). When a tag is + specified, any records with different tags are silently omitted. The + tag is ignored. The tag is ignores for fixed-length prefixes. + + The binary stream containing the serialized records. + The prefix style used in the data. + The tag of records to return (if non-positive, then no tag is + expected and all records are returned). + On a field-by-field basis, the type of object to deserialize (can be null if "type" is specified). + The type of object to deserialize (can be null if "resolver" is specified). + The sequence of deserialized objects. + Additional information about this serialization operation. + + + + Reads a sequence of consecutive length-prefixed items from a stream, using + either base-128 or fixed-length prefixes. Base-128 prefixes with a tag + are directly comparable to serializing multiple items in succession + (use the tag to emulate the implicit behavior + when serializing a list/array). When a tag is + specified, any records with different tags are silently omitted. The + tag is ignored. The tag is ignores for fixed-length prefixes. + + The type of object to deserialize. + The binary stream containing the serialized records. + The prefix style used in the data. + The tag of records to return (if non-positive, then no tag is + expected and all records are returned). + The sequence of deserialized objects. + + + + Reads a sequence of consecutive length-prefixed items from a stream, using + either base-128 or fixed-length prefixes. Base-128 prefixes with a tag + are directly comparable to serializing multiple items in succession + (use the tag to emulate the implicit behavior + when serializing a list/array). When a tag is + specified, any records with different tags are silently omitted. The + tag is ignored. The tag is ignores for fixed-length prefixes. + + The type of object to deserialize. + The binary stream containing the serialized records. + The prefix style used in the data. + The tag of records to return (if non-positive, then no tag is + expected and all records are returned). + The sequence of deserialized objects. + Additional information about this serialization operation. + + + + Writes a protocol-buffer representation of the given instance to the supplied stream, + with a length-prefix. This is useful for socket programming, + as DeserializeWithLengthPrefix can be used to read the single object back + from an ongoing stream. + + The type being serialized. + The existing instance to be serialized (cannot be null). + How to encode the length prefix. + The destination stream to write to. + The tag used as a prefix to each record (only used with base-128 style prefixes). + + + + Writes a protocol-buffer representation of the given instance to the supplied stream, + with a length-prefix. This is useful for socket programming, + as DeserializeWithLengthPrefix can be used to read the single object back + from an ongoing stream. + + The type being serialized. + The existing instance to be serialized (cannot be null). + How to encode the length prefix. + The destination stream to write to. + The tag used as a prefix to each record (only used with base-128 style prefixes). + Additional information about this serialization operation. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + The type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + The type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + Additional information about this serialization operation. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + The type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The number of bytes to consume. + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + The type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The number of bytes to consume (or -1 to read to the end of the stream). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + Additional information about this serialization operation. + + + + Applies a protocol-buffer reader to an existing instance (which may be null). + + The type (including inheritance) to consider. + The existing instance to be modified (can be null). + The reader to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + This is the more "complete" version of Deserialize, which handles single instances of mapped types. + The value is read as a complete field, including field-header and (for sub-objects) a + length-prefix..kmc + + In addition to that, this provides support for: + - basic values; individual int / string / Guid / etc + - IList sets of any type handled by TryDeserializeAuxiliaryType + + + + + Creates a new runtime model, to which the caller + can add support for a range of types. A model + can be used "as is", or can be compiled for + optimal performance. + + + + + Applies common proxy scenarios, resolving the actual type to consider + + + + + Indicates whether the supplied type is explicitly modelled by the model + + + + + Provides the key that represents a given type in the current model. + The type is also normalized for proxies at the same time. + + + + + Provides the key that represents a given type in the current model. + + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + Represents the type (including inheritance) to consider. + The existing instance to be serialized (cannot be null). + The destination stream to write to. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + Represents the type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Create a deep clone of the supplied instance; any sub-items are also cloned. + + + + + Indicates that while an inheritance tree exists, the exact type encountered was not + specified in that hierarchy and cannot be processed. + + + + + Indicates that the given type was not expected, and cannot be processed. + + + + + Indicates that the given type cannot be constructed; it may still be possible to + deserialize into existing instances. + + + + + Returns true if the type supplied is either a recognised contract type, + or a *list* of a recognised contract type. + + Note that primitives always return false, even though the engine + will, if forced, try to serialize such + True if this type is recognised as a serializable entity, else false + + + + Returns true if the type supplied is a basic type with inbuilt handling, + a recognised contract type, or a *list* of a basic / contract type. + + + + + Returns true if the type supplied is a basic type with inbuilt handling, + or a *list* of a basic type with inbuilt handling + + + + + Suggest a .proto definition for the given type + + The type to generate a .proto definition for, or null to generate a .proto that represents the entire model + The .proto definition as a string + + + + Creates a new IFormatter that uses protocol-buffer [de]serialization. + + A new IFormatter to be used during [de]serialization. + The type of object to be [de]deserialized by the formatter. + + + + Used to provide custom services for writing and parsing type names when using dynamic types. Both parsing and formatting + are provided on a single API as it is essential that both are mapped identically at all times. + + + + + Indicates the type of callback to be used + + + + + Invoked before an object is serialized + + + + + Invoked after an object is serialized + + + + + Invoked before an object is deserialized (or when a new instance is created) + + + + + Invoked after an object is deserialized + + + + + Returns a sequence of the Type instances that can be + processed by this model. + + + + + Suggest a .proto definition for the given type + + The type to generate a .proto definition for, or null to generate a .proto that represents the entire model + The .proto definition as a string + + + + Adds support for an additional type in this model, optionally + appplying inbuilt patterns. If the type is already known to the + model, the existing type is returned **without** applying + any additional behaviour. + + Inbuilt patterns include: + [ProtoContract]/[ProtoMember(n)] + [DataContract]/[DataMember(Order=n)] + [XmlType]/[XmlElement(Order=n)] + [On{Des|S}erializ{ing|ed}] + ShouldSerialize*/*Specified + + The type to be supported + Whether to apply the inbuilt configuration patterns (via attributes etc), or + just add the type with no additional configuration (the type must then be manually configured). + The MetaType representing this type, allowing + further configuration. + + + + Verifies that the model is still open to changes; if not, an exception is thrown + + + + + Prevents further changes to this model + + + + + Provides the key that represents a given type in the current model. + + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + Represents the type (including inheritance) to consider. + The existing instance to be serialized (cannot be null). + The destination stream to write to. + + + + Applies a protocol-buffer stream to an existing instance (which may be null). + + Represents the type (including inheritance) to consider. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Compiles the serializers individually; this is *not* a full + standalone compile, but can significantly boost performance + while allowing additional types to be added. + + An in-place compile can access non-public types / members + + + + Fully compiles the current model into a static-compiled model instance + + A full compilation is restricted to accessing public types / members + An instance of the newly created compiled type-model + + + + Fully compiles the current model into a static-compiled serialization dll + (the serialization dll still requires protobuf-net for support services). + + A full compilation is restricted to accessing public types / members + The name of the TypeModel class to create + The path for the new dll + An instance of the newly created compiled type-model + + + + Fully compiles the current model into a static-compiled serialization dll + (the serialization dll still requires protobuf-net for support services). + + A full compilation is restricted to accessing public types / members + An instance of the newly created compiled type-model + + + + Designate a factory-method to use to create instances of any type; note that this only affect types seen by the serializer *after* setting the factory. + + + + + Global default that + enables/disables automatic tag generation based on the existing name / order + of the defined members. See + for usage and important warning / explanation. + You must set the global default before attempting to serialize/deserialize any + impacted type. + + + + + Global default that determines whether types are considered serializable + if they have [DataContract] / [XmlType]. With this enabled, ONLY + types marked as [ProtoContract] are added automatically. + + + + + Global switch that enables or disables the implicit + handling of "zero defaults"; meanning: if no other default is specified, + it assumes bools always default to false, integers to zero, etc. + + If this is disabled, no such assumptions are made and only *explicit* + default values are processed. This is enabled by default to + preserve similar logic to v1. + + + + + Global switch that determines whether types with a .ToString() and a Parse(string) + should be serialized as strings. + + + + + The default model, used to support ProtoBuf.Serializer + + + + + Obtains the MetaType associated with a given Type for the current model, + allowing additional configuration. + + + + + Should serializers be compiled on demand? It may be useful + to disable this for debugging purposes. + + + + + Should support for unexpected types be added automatically? + If false, an exception is thrown when unexpected types + are encountered. + + + + + The amount of time to wait if there are concurrent metadata access operations + + + + + If a lock-contention is detected, this event signals the *owner* of the lock responsible for the blockage, indicating + what caused the problem; this is only raised if the lock-owning code successfully completes. + + + + + Represents configuration options for compiling a model to + a standalone assembly. + + + + + Import framework options from an existing type + + + + + The TargetFrameworkAttribute FrameworkName value to burn into the generated assembly + + + + + The TargetFrameworkAttribute FrameworkDisplayName value to burn into the generated assembly + + + + + The name of the TypeModel class to create + + + + + The path for the new dll + + + + + The runtime version for the generated assembly + + + + + The runtime version for the generated assembly + + + + + The acecssibility of the generated serializer + + + + + Type accessibility + + + + + Available to all callers + + + + + Available to all callers in the same assembly, or assemblies specified via [InternalsVisibleTo(...)] + + + + + Contains the stack-trace of the owning code when a lock-contention scenario is detected + + + + + The stack-trace of the code that owned the lock when a lock-contention scenario occurred + + + + + Event-type that is raised when a lock-contention scenario is detected + + + + + Represents an inherited type in a type hierarchy. + + + + + Creates a new SubType instance. + + The field-number that is used to encapsulate the data (as a nested + message) for the derived dype. + The sub-type to be considered. + Specific encoding style to use; in particular, Grouped can be used to avoid buffering, but is not the default. + + + + The field-number that is used to encapsulate the data (as a nested + message) for the derived dype. + + + + + The sub-type to be considered. + + + + + Event arguments needed to perform type-formatting functions; this could be resolving a Type to a string suitable for serialization, or could + be requesting a Type from a string. If no changes are made, a default implementation will be used (from the assembly-qualified names). + + + + + The type involved in this map; if this is initially null, a Type is expected to be provided for the string in FormattedName. + + + + + The formatted-name involved in this map; if this is initially null, a formatted-name is expected from the type in Type. + + + + + Delegate type used to perform type-formatting functions; the sender originates as the type-model. + + + + + Represents a member (property/field) that is mapped to a protobuf field + + + + + Creates a new ValueMember instance + + + + + Creates a new ValueMember instance + + + + + Specifies methods for working with optional data members. + + Provides a method (null for none) to query whether this member should + be serialized; it must be of the form "bool {Method}()". The member is only serialized if the + method returns true. + Provides a method (null for none) to indicate that a member was + deserialized; it must be of the form "void {Method}(bool)", and will be called with "true" + when data is found. + + + + The number that identifies this member in a protobuf stream + + + + + Gets the member (field/property) which this member relates to. + + + + + Within a list / array / etc, the type of object for each item in the list (especially useful with ArrayList) + + + + + The underlying type of the member + + + + + For abstract types (IList etc), the type of concrete object to create (if required) + + + + + The type the defines the member + + + + + The default value of the item (members with this value will not be serialized) + + + + + Specifies the rules used to process the field; this is used to determine the most appropriate + wite-type, but also to describe subtypes within that wire-type (such as SignedVariant) + + + + + Indicates whether this field should follow strict encoding rules; this means (for example) that if a "fixed32" + is encountered when "variant" is defined, then it will fail (throw an exception) when parsing. Note that + when serializing the defined type is always used. + + + + + Indicates whether this field should use packed encoding (which can save lots of space for repeated primitive values). + This option only applies to list/array data of primitive types (int, double, etc). + + + + + Indicates whether this field should *repace* existing values (the default is false, meaning *append*). + This option only applies to list/array data. + + + + + Indicates whether this field is mandatory. + + + + + Enables full object-tracking/full-graph support. + + + + + Embeds the type information into the stream, allowing usage with types not known in advance. + + + + + Gets the logical name for this member in the schema (this is not critical for binary serialization, but may be used + when inferring a schema). + + + + + Should lists have extended support for null values? Note this makes the serialization less efficient. + + + + + Specifies the type of prefix that should be applied to messages. + + + + + No length prefix is applied to the data; the data is terminated only be the end of the stream. + + + + + A base-128 length prefix is applied to the data (efficient for short messages). + + + + + A fixed-length (little-endian) length prefix is applied to the data (useful for compatibility). + + + + + A fixed-length (big-endian) length prefix is applied to the data (useful for compatibility). + + + + + Indicates that a type is defined for protocol-buffer serialization. + + + + + Gets or sets the defined name of the type. + + + + + Gets or sets the fist offset to use with implicit field tags; + only uesd if ImplicitFields is set. + + + + + If specified, alternative contract markers (such as markers for XmlSerailizer or DataContractSerializer) are ignored. + + + + + If specified, do NOT treat this type as a list, even if it looks like one. + + + + + Gets or sets the mechanism used to automatically infer field tags + for members. This option should be used in advanced scenarios only. + Please review the important notes against the ImplicitFields enumeration. + + + + + Enables/disables automatic tag generation based on the existing name / order + of the defined members. This option is not used for members marked + with ProtoMemberAttribute, as intended to provide compatibility with + WCF serialization. WARNING: when adding new fields you must take + care to increase the Order for new elements, otherwise data corruption + may occur. + + If not explicitly specified, the default is assumed from Serializer.GlobalOptions.InferTagFromName. + + + + Has a InferTagFromName value been explicitly set? if not, the default from the type-model is assumed. + + + + + Specifies an offset to apply to [DataMember(Order=...)] markers; + this is useful when working with mex-generated classes that have + a different origin (usually 1 vs 0) than the original data-contract. + + This value is added to the Order of each member. + + + + + If true, the constructor for the type is bypassed during deserialization, meaning any field initializers + or other initialization code is skipped. + + + + + Should this type be treated as a reference by default? Please also see the implications of this, + as recorded on ProtoMemberAttribute.AsReference + + + + + Used to define protocol-buffer specific behavior for + enumerated values. + + + + + Indicates whether this instance has a customised value mapping + + true if a specific value is set + + + + Gets or sets the specific value to use for this enum during serialization. + + + + + Gets or sets the defined name of the enum, as used in .proto + (this name is not used during serialization). + + + + + Indicates an error during serialization/deserialization of a proto stream. + + + + Creates a new ProtoException instance. + + + Creates a new ProtoException instance. + + + Creates a new ProtoException instance. + + + Creates a new ProtoException instance. + + + + Indicates that a member should be excluded from serialization; this + is only normally used when using implict fields. + + + + + Indicates that a member should be excluded from serialization; this + is only normally used when using implict fields. This allows + ProtoIgnoreAttribute usage + even for partial classes where the individual members are not + under direct control. + + + + + Creates a new ProtoPartialIgnoreAttribute instance. + + Specifies the member to be ignored. + + + + The name of the member to be ignored. + + + + + Indicates the known-types to support for an individual + message. This serializes each level in the hierarchy as + a nested message to retain wire-compatibility with + other protocol-buffer implementations. + + + + + Creates a new instance of the ProtoIncludeAttribute. + + The unique index (within the type) that will identify this data. + The additional type to serialize/deserialize. + + + + Creates a new instance of the ProtoIncludeAttribute. + + The unique index (within the type) that will identify this data. + The additional type to serialize/deserialize. + + + + Gets the unique index (within the type) that will identify this data. + + + + + Gets the additional type to serialize/deserialize. + + + + + Gets the additional type to serialize/deserialize. + + + + + Specifies whether the inherited sype's sub-message should be + written with a length-prefix (default), or with group markers. + + + + + Declares a member to be used in protocol-buffer serialization, using + the given Tag. A DataFormat may be used to optimise the serialization + format (for instance, using zigzag encoding for negative numbers, or + fixed-length encoding for large values. + + + + + Compare with another ProtoMemberAttribute for sorting purposes + + + + + Compare with another ProtoMemberAttribute for sorting purposes + + + + + Creates a new ProtoMemberAttribute instance. + + Specifies the unique tag used to identify this member within the type. + + + + Gets or sets the original name defined in the .proto; not used + during serialization. + + + + + Gets or sets the data-format to be used when encoding this value. + + + + + Gets the unique tag used to identify this member within the type. + + + + + Gets or sets a value indicating whether this member is mandatory. + + + + + Gets a value indicating whether this member is packed. + This option only applies to list/array data of primitive types (int, double, etc). + + + + + Indicates whether this field should *repace* existing values (the default is false, meaning *append*). + This option only applies to list/array data. + + + + + Enables full object-tracking/full-graph support. + + + + + Embeds the type information into the stream, allowing usage with types not known in advance. + + + + + Gets or sets a value indicating whether this member is packed (lists/arrays). + + + + + Additional (optional) settings that control serialization of members + + + + + Default; no additional options + + + + + Indicates that repeated elements should use packed (length-prefixed) encoding + + + + + Indicates that the given item is required + + + + + Enables full object-tracking/full-graph support + + + + + Embeds the type information into the stream, allowing usage with types not known in advance + + + + + Indicates whether this field should *repace* existing values (the default is false, meaning *append*). + This option only applies to list/array data. + + + + + Determines whether the types AsReferenceDefault value is used, or whether this member's AsReference should be used + + + + + Declares a member to be used in protocol-buffer serialization, using + the given Tag and MemberName. This allows ProtoMemberAttribute usage + even for partial classes where the individual members are not + under direct control. + A DataFormat may be used to optimise the serialization + format (for instance, using zigzag encoding for negative numbers, or + fixed-length encoding for large values. + + + + + Creates a new ProtoMemberAttribute instance. + + Specifies the unique tag used to identify this member within the type. + Specifies the member to be serialized. + + + + The name of the member to be serialized. + + + + + A stateful reader, used to read a protobuf stream. Typical usage would be (sequentially) to call + ReadFieldHeader and (after matching the field) an appropriate Read* method. + + + + + Creates a new reader against a stream + + The source stream + The model to use for serialization; this can be null, but this will impair the ability to deserialize sub-objects + Additional context about this serialization operation + + + + Creates a new reader against a stream + + The source stream + The model to use for serialization; this can be null, but this will impair the ability to deserialize sub-objects + Additional context about this serialization operation + The number of bytes to read, or -1 to read until the end of the stream + + + + Releases resources used by the reader, but importantly does not Dispose the + underlying stream; in many typical use-cases the stream is used for different + processes, so it is assumed that the consumer will Dispose their stream separately. + + + + + Reads an unsigned 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Reads a signed 16-bit integer from the stream: Variant, Fixed32, Fixed64, SignedVariant + + + + + Reads an unsigned 16-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Reads an unsigned 8-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Reads a signed 8-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Reads a signed 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Reads a signed 64-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Reads a string from the stream (using UTF8); supported wire-types: String + + + + + Throws an exception indication that the given value cannot be mapped to an enum. + + + + + Reads a double-precision number from the stream; supported wire-types: Fixed32, Fixed64 + + + + + Reads (merges) a sub-message from the stream, internally calling StartSubItem and EndSubItem, and (in between) + parsing the message in accordance with the model associated with the reader + + + + + Makes the end of consuming a nested message in the stream; the stream must be either at the correct EndGroup + marker, or all fields of the sub-message must have been consumed (in either case, this means ReadFieldHeader + should return zero) + + + + + Begins consuming a nested message in the stream; supported wire-types: StartGroup, String + + The token returned must be help and used when callining EndSubItem + + + + Reads a field header from the stream, setting the wire-type and retuning the field number. If no + more fields are available, then 0 is returned. This methods respects sub-messages. + + + + + Looks ahead to see whether the next field in the stream is what we expect + (typically; what we've just finished reading - for example ot read successive list items) + + + + + Compares the streams current wire-type to the hinted wire-type, updating the reader if necessary; for example, + a Variant may be updated to SignedVariant. If the hinted wire-type is unrelated then no change is made. + + + + + Verifies that the stream's current wire-type is as expected, or a specialized sub-type (for example, + SignedVariant) - in which case the current wire-type is updated. Otherwise an exception is thrown. + + + + + Discards the data for the current field. + + + + + Reads an unsigned 64-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Reads a single-precision number from the stream; supported wire-types: Fixed32, Fixed64 + + + + + Reads a boolean value from the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + + Reads a byte-sequence from the stream, appending them to an existing byte-sequence (which can be null); supported wire-types: String + + + + + Reads the length-prefix of a message from a stream without buffering additional data, allowing a fixed-length + reader to be created. + + + + + Reads a little-endian encoded integer. An exception is thrown if the data is not all available. + + + + + Reads a big-endian encoded integer. An exception is thrown if the data is not all available. + + + + + Reads a varint encoded integer. An exception is thrown if the data is not all available. + + + + + Reads a string (of a given lenth, in bytes) directly from the source into a pre-existing buffer. An exception is thrown if the data is not all available. + + + + + Reads a given number of bytes directly from the source. An exception is thrown if the data is not all available. + + + + + Reads a string (of a given lenth, in bytes) directly from the source. An exception is thrown if the data is not all available. + + + + + Reads the length-prefix of a message from a stream without buffering additional data, allowing a fixed-length + reader to be created. + + + + The number of bytes consumed; 0 if no data available + + + + Copies the current field into the instance as extension data + + + + + Indicates whether the reader still has data remaining in the current sub-item, + additionally setting the wire-type for the next field if there is more data. + This is used when decoding packed data. + + + + + Utility method, not intended for public use; this helps maintain the root object is complex scenarios + + + + + Reads a Type from the stream, using the model's DynamicTypeFormatting if appropriate; supported wire-types: String + + + + + Merge two objects using the details from the current reader; this is used to change the type + of objects when an inheritance relationship is discovered later than usual during deserilazation. + + + + + Gets the number of the field being processed. + + + + + Indicates the underlying proto serialization format on the wire. + + + + + Gets / sets a flag indicating whether strings should be checked for repetition; if + true, any repeated UTF-8 byte sequence will result in the same String instance, rather + than a second instance of the same string. Enabled by default. Note that this uses + a custom interner - the system-wide string interner is not used. + + + + + Addition information about this deserialization operation. + + + + + Returns the position of the current reader (note that this is not necessarily the same as the position + in the underlying stream, if multiple readers are used on the same stream) + + + + + Get the TypeModel associated with this reader + + + + + Represents an output stream for writing protobuf data. + + Why is the API backwards (static methods with writer arguments)? + See: http://marcgravell.blogspot.com/2010/03/last-will-be-first-and-first-will-be.html + + + + + Write an encapsulated sub-object, using the supplied unique key (reprasenting a type). + + The object to write. + The key that uniquely identifies the type within the model. + The destination. + + + + Write an encapsulated sub-object, using the supplied unique key (reprasenting a type) - but the + caller is asserting that this relationship is non-recursive; no recursion check will be + performed. + + The object to write. + The key that uniquely identifies the type within the model. + The destination. + + + + Writes a field-header, indicating the format of the next data we plan to write. + + + + + Writes a byte-array to the stream; supported wire-types: String + + + + + Writes a byte-array to the stream; supported wire-types: String + + + + + Indicates the start of a nested record. + + The instance to write. + The destination. + A token representing the state of the stream; this token is given to EndSubItem. + + + + Indicates the end of a nested record. + + The token obtained from StartubItem. + The destination. + + + + Creates a new writer against a stream + + The destination stream + The model to use for serialization; this can be null, but this will impair the ability to serialize sub-objects + Additional context about this serialization operation + + + + Flushes data to the underlying stream, and releases any resources. The underlying stream is *not* disposed + by this operation. + + + + + Writes any buffered data (if possible) to the underlying stream. + + The writer to flush + It is not always possible to fully flush, since some sequences + may require values to be back-filled into the byte-stream. + + + + Writes an unsigned 32-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Writes a string to the stream; supported wire-types: String + + + + + Writes an unsigned 64-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Writes a signed 64-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Writes an unsigned 16-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Writes a signed 16-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Writes an unsigned 16-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Writes an unsigned 8-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Writes a signed 8-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Writes a signed 32-bit integer to the stream; supported wire-types: Variant, Fixed32, Fixed64, SignedVariant + + + + + Writes a double-precision number to the stream; supported wire-types: Fixed32, Fixed64 + + + + + Writes a single-precision number to the stream; supported wire-types: Fixed32, Fixed64 + + + + + Throws an exception indicating that the given enum cannot be mapped to a serialized value. + + + + + Writes a boolean to the stream; supported wire-types: Variant, Fixed32, Fixed64 + + + + + Copies any extension data stored for the instance to the underlying stream + + + + + Used for packed encoding; indicates that the next field should be skipped rather than + a field header written. Note that the field number must match, else an exception is thrown + when the attempt is made to write the (incorrect) field. The wire-type is taken from the + subsequent call to WriteFieldHeader. Only primitive types can be packed. + + + + + Specifies a known root object to use during reference-tracked serialization + + + + + Writes a Type to the stream, using the model's DynamicTypeFormatting if appropriate; supported wire-types: String + + + + + Addition information about this serialization operation. + + + + + Get the TypeModel associated with this writer + + + + + Additional information about a serialization operation + + + + + Convert a SerializationContext to a StreamingContext + + + + + Convert a StreamingContext to a SerializationContext + + + + + Gets or sets a user-defined object containing additional information about this serialization/deserialization operation. + + + + + A default SerializationContext, with minimal information. + + + + + Gets or sets the source or destination of the transmitted data. + + + + + Provides protocol-buffer serialization capability for concrete, attributed types. This + is a *default* model, but custom serializer models are also supported. + + + Protocol-buffer serialization is a compact binary format, designed to take + advantage of sparse data and knowledge of specific data types; it is also + extensible, allowing a type to be deserialized / merged even if some data is + not recognised. + + + + + The field number that is used as a default when serializing/deserializing a list of objects. + The data is treated as repeated message with field number 1. + + + + + Suggest a .proto definition for the given type + + The type to generate a .proto definition for + The .proto definition as a string + + + + Create a deep clone of the supplied instance; any sub-items are also cloned. + + + + + Applies a protocol-buffer stream to an existing instance. + + The type being merged. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Creates a new instance from a protocol-buffer stream + + The type to be created. + The binary stream to apply to the new instance (cannot be null). + A new, initialized instance. + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + The existing instance to be serialized (cannot be null). + The destination stream to write to. + + + + Serializes a given instance and deserializes it as a different type; + this can be used to translate between wire-compatible objects (where + two .NET types represent the same data), or to promote/demote a type + through an inheritance hierarchy. + + No assumption of compatibility is made between the types. + The type of the object being copied. + The type of the new object to be created. + The existing instance to use as a template. + A new instane of type TNewType, with the data from TOldType. + + + + Writes a protocol-buffer representation of the given instance to the supplied SerializationInfo. + + The type being serialized. + The existing instance to be serialized (cannot be null). + The destination SerializationInfo to write to. + + + + Writes a protocol-buffer representation of the given instance to the supplied SerializationInfo. + + The type being serialized. + The existing instance to be serialized (cannot be null). + The destination SerializationInfo to write to. + Additional information about this serialization operation. + + + + Writes a protocol-buffer representation of the given instance to the supplied XmlWriter. + + The type being serialized. + The existing instance to be serialized (cannot be null). + The destination XmlWriter to write to. + + + + Applies a protocol-buffer from an XmlReader to an existing instance. + + The type being merged. + The existing instance to be modified (cannot be null). + The XmlReader containing the data to apply to the instance (cannot be null). + + + + Applies a protocol-buffer from a SerializationInfo to an existing instance. + + The type being merged. + The existing instance to be modified (cannot be null). + The SerializationInfo containing the data to apply to the instance (cannot be null). + + + + Applies a protocol-buffer from a SerializationInfo to an existing instance. + + The type being merged. + The existing instance to be modified (cannot be null). + The SerializationInfo containing the data to apply to the instance (cannot be null). + Additional information about this serialization operation. + + + + Precompiles the serializer for a given type. + + + + + Creates a new IFormatter that uses protocol-buffer [de]serialization. + + The type of object to be [de]deserialized by the formatter. + A new IFormatter to be used during [de]serialization. + + + + Reads a sequence of consecutive length-prefixed items from a stream, using + either base-128 or fixed-length prefixes. Base-128 prefixes with a tag + are directly comparable to serializing multiple items in succession + (use the tag to emulate the implicit behavior + when serializing a list/array). When a tag is + specified, any records with different tags are silently omitted. The + tag is ignored. The tag is ignores for fixed-length prefixes. + + The type of object to deserialize. + The binary stream containing the serialized records. + The prefix style used in the data. + The tag of records to return (if non-positive, then no tag is + expected and all records are returned). + The sequence of deserialized objects. + + + + Creates a new instance from a protocol-buffer stream that has a length-prefix + on data (to assist with network IO). + + The type to be created. + The binary stream to apply to the new instance (cannot be null). + How to encode the length prefix. + A new, initialized instance. + + + + Creates a new instance from a protocol-buffer stream that has a length-prefix + on data (to assist with network IO). + + The type to be created. + The binary stream to apply to the new instance (cannot be null). + How to encode the length prefix. + The expected tag of the item (only used with base-128 prefix style). + A new, initialized instance. + + + + Applies a protocol-buffer stream to an existing instance, using length-prefixed + data - useful with network IO. + + The type being merged. + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + How to encode the length prefix. + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Writes a protocol-buffer representation of the given instance to the supplied stream, + with a length-prefix. This is useful for socket programming, + as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back + from an ongoing stream. + + The type being serialized. + The existing instance to be serialized (cannot be null). + How to encode the length prefix. + The destination stream to write to. + + + + Writes a protocol-buffer representation of the given instance to the supplied stream, + with a length-prefix. This is useful for socket programming, + as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back + from an ongoing stream. + + The type being serialized. + The existing instance to be serialized (cannot be null). + How to encode the length prefix. + The destination stream to write to. + The tag used as a prefix to each record (only used with base-128 style prefixes). + + + Indicates the number of bytes expected for the next message. + The stream containing the data to investigate for a length. + The algorithm used to encode the length. + The length of the message, if it could be identified. + True if a length could be obtained, false otherwise. + + + Indicates the number of bytes expected for the next message. + The buffer containing the data to investigate for a length. + The offset of the first byte to read from the buffer. + The number of bytes to read from the buffer. + The algorithm used to encode the length. + The length of the message, if it could be identified. + True if a length could be obtained, false otherwise. + + + + Releases any internal buffers that have been reserved for efficiency; this does not affect any serialization + operations; simply: it can be used (optionally) to release the buffers for garbage collection (at the expense + of having to re-allocate a new buffer for the next operation, rather than re-use prior buffers). + + + + + Provides non-generic access to the default serializer. + + + + + Create a deep clone of the supplied instance; any sub-items are also cloned. + + + + + Writes a protocol-buffer representation of the given instance to the supplied stream. + + The existing instance to be serialized (cannot be null). + The destination stream to write to. + + + + Creates a new instance from a protocol-buffer stream + + The type to be created. + The binary stream to apply to the new instance (cannot be null). + A new, initialized instance. + + + Applies a protocol-buffer stream to an existing instance. + The existing instance to be modified (cannot be null). + The binary stream to apply to the instance (cannot be null). + The updated instance + + + + Writes a protocol-buffer representation of the given instance to the supplied stream, + with a length-prefix. This is useful for socket programming, + as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back + from an ongoing stream. + + The existing instance to be serialized (cannot be null). + How to encode the length prefix. + The destination stream to write to. + The tag used as a prefix to each record (only used with base-128 style prefixes). + + + + Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed + data - useful with network IO. + + The existing instance to be modified (can be null). + The binary stream to apply to the instance (cannot be null). + How to encode the length prefix. + Used to resolve types on a per-field basis. + The updated instance; this may be different to the instance argument if + either the original instance was null, or the stream defines a known sub-type of the + original instance. + + + + Indicates whether the supplied type is explicitly modelled by the model + + + + + Global switches that change the behavior of protobuf-net + + + + + + + + + + Maps a field-number to a type + + + + + Perform the steps necessary to serialize this data. + + The value to be serialized. + The writer entity that is accumulating the output data. + + + + Perform the steps necessary to deserialize this data. + + The current value, if appropriate. + The reader providing the input data. + The updated / replacement value. + + + Emit the IL necessary to perform the given actions + to serialize this data. + + Details and utilities for the method being generated. + The source of the data to work against; + If the value is only needed once, then LoadValue is sufficient. If + the value is needed multiple times, then note that a "null" + means "the top of the stack", in which case you should create your + own copy - GetLocalWithValue. + + + + Emit the IL necessary to perform the given actions to deserialize this data. + + Details and utilities for the method being generated. + For nested values, the instance holding the values; note + that this is not always provided - a null means not supplied. Since this is always + a variable or argument, it is not necessary to consume this value. + + + + The type that this serializer is intended to work for. + + + + + Indicates whether a Read operation replaces the existing value, or + extends the value. If false, the "value" parameter to Read is + discarded, and should be passed in as null. + + + + + Now all Read operations return a value (although most do); if false no + value should be expected. + + + + + Used to hold particulars relating to nested objects. This is opaque to the caller - simply + give back the token you are given at the end of an object. + + + + + Indicates the encoding used to represent an individual value in a protobuf stream + + + + + Represents an error condition + + + + + Base-128 variant-length encoding + + + + + Fixed-length 8-byte encoding + + + + + Length-variant-prefixed encoding + + + + + Indicates the start of a group + + + + + Indicates the end of a group + + + + + Fixed-length 4-byte encoding + 10 + + + + This is not a formal wire-type in the "protocol buffers" spec, but + denotes a variant integer that should be interpreted using + zig-zag semantics (so -ve numbers aren't a significant overhead) + + + +