Example #1
0
        /// <summary>
        /// Parses a decimal from a protobuf stream
        /// </summary>
        public static decimal ReadDecimal(ProtoReader reader)
        {
            ulong low       = 0;
            uint  high      = 0;
            uint  signScale = 0;

            int          fieldNumber;
            SubItemToken token = ProtoReader.StartSubItem(reader);

            while ((fieldNumber = reader.ReadFieldHeader()) > 0)
            {
                switch (fieldNumber)
                {
                case FieldDecimalLow: low = reader.ReadUInt64(); break;

                case FieldDecimalHigh: high = reader.ReadUInt32(); break;

                case FieldDecimalSignScale: signScale = reader.ReadUInt32(); break;

                default: reader.SkipField(); break;
                }
            }
            ProtoReader.EndSubItem(token, reader);

            if (low == 0 && high == 0)
            {
                return(decimal.Zero);
            }

            int lo     = (int)(low & 0xFFFFFFFFL),
                mid    = (int)((low >> 32) & 0xFFFFFFFFL),
                hi     = (int)high;
            bool isNeg = (signScale & 0x0001) == 0x0001;
            byte scale = (byte)((signScale & 0x01FE) >> 1);

            return(new decimal(lo, mid, hi, isNeg, scale));
        }
Example #2
0
        private static void WriteTimeSpanImpl(TimeSpan timeSpan, ProtoWriter dest, DateTimeKind kind)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }
            switch (dest.WireType)
            {
            case WireType.String:
            case WireType.StartGroup:
                TimeSpanScale scale;
                long          value = timeSpan.Ticks;
                if (timeSpan == TimeSpan.MaxValue)
                {
                    value = 1;
                    scale = TimeSpanScale.MinMax;
                }
                else if (timeSpan == TimeSpan.MinValue)
                {
                    value = -1;
                    scale = TimeSpanScale.MinMax;
                }
                else if (value % TimeSpan.TicksPerDay == 0)
                {
                    scale  = TimeSpanScale.Days;
                    value /= TimeSpan.TicksPerDay;
                }
                else if (value % TimeSpan.TicksPerHour == 0)
                {
                    scale  = TimeSpanScale.Hours;
                    value /= TimeSpan.TicksPerHour;
                }
                else if (value % TimeSpan.TicksPerMinute == 0)
                {
                    scale  = TimeSpanScale.Minutes;
                    value /= TimeSpan.TicksPerMinute;
                }
                else if (value % TimeSpan.TicksPerSecond == 0)
                {
                    scale  = TimeSpanScale.Seconds;
                    value /= TimeSpan.TicksPerSecond;
                }
                else if (value % TimeSpan.TicksPerMillisecond == 0)
                {
                    scale  = TimeSpanScale.Milliseconds;
                    value /= TimeSpan.TicksPerMillisecond;
                }
                else
                {
                    scale = TimeSpanScale.Ticks;
                }

                SubItemToken token = ProtoWriter.StartSubItemWithoutWritingHeader(null, dest);

                if (value != 0)
                {
                    ProtoWriter.WriteFieldHeader(FieldTimeSpanValue, WireType.SignedVariant, dest);
                    ProtoWriter.WriteInt64(value, dest);
                }
                if (scale != TimeSpanScale.Days)
                {
                    ProtoWriter.WriteFieldHeader(FieldTimeSpanScale, WireType.Variant, dest);
                    ProtoWriter.WriteInt32((int)scale, dest);
                }
                if (kind != DateTimeKind.Unspecified)
                {
                    ProtoWriter.WriteFieldHeader(FieldTimeSpanKind, WireType.Variant, dest);
                    ProtoWriter.WriteInt32((int)kind, dest);
                }
                ProtoWriter.EndSubItem(token, dest);
                break;

            case WireType.Fixed64:
                ProtoWriter.WriteInt64(timeSpan.Ticks, dest);
                break;

            default:
                throw new ProtoException("Unexpected wire-type: " + dest.WireType.ToString());
            }
        }
Example #3
0
        private static long ReadTimeSpanTicks(ProtoReader source, out DateTimeKind kind)
        {
            kind = DateTimeKind.Unspecified;
            switch (source.WireType)
            {
            case WireType.String:
            case WireType.StartGroup:
                SubItemToken  token = ProtoReader.StartSubItem(source);
                int           fieldNumber;
                TimeSpanScale scale = TimeSpanScale.Days;
                long          value = 0;
                while ((fieldNumber = source.ReadFieldHeader()) > 0)
                {
                    switch (fieldNumber)
                    {
                    case FieldTimeSpanScale:
                        scale = (TimeSpanScale)source.ReadInt32();
                        break;

                    case FieldTimeSpanValue:
                        source.Assert(WireType.SignedVariant);
                        value = source.ReadInt64();
                        break;

                    case FieldTimeSpanKind:
                        kind = (DateTimeKind)source.ReadInt32();
                        switch (kind)
                        {
                        case DateTimeKind.Unspecified:
                        case DateTimeKind.Utc:
                        case DateTimeKind.Local:
                            break;             // fine

                        default:
                            throw new ProtoException("Invalid date/time kind: " + kind.ToString());
                        }
                        break;

                    default:
                        source.SkipField();
                        break;
                    }
                }
                ProtoReader.EndSubItem(token, source);
                switch (scale)
                {
                case TimeSpanScale.Days:
                    return(value * TimeSpan.TicksPerDay);

                case TimeSpanScale.Hours:
                    return(value * TimeSpan.TicksPerHour);

                case TimeSpanScale.Minutes:
                    return(value * TimeSpan.TicksPerMinute);

                case TimeSpanScale.Seconds:
                    return(value * TimeSpan.TicksPerSecond);

                case TimeSpanScale.Milliseconds:
                    return(value * TimeSpan.TicksPerMillisecond);

                case TimeSpanScale.Ticks:
                    return(value);

                case TimeSpanScale.MinMax:
                    switch (value)
                    {
                    case 1: return(long.MaxValue);

                    case -1: return(long.MinValue);

                    default: throw new ProtoException("Unknown min/max value: " + value.ToString());
                    }

                default:
                    throw new ProtoException("Unknown timescale: " + scale.ToString());
                }

            case WireType.Fixed64:
                return(source.ReadInt64());

            default:
                throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString());
            }
        }
        /// <summary>
        /// Writes an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc.
        /// </summary>
        public static SubItemToken WriteNetObject_Start(object value, ProtoWriter dest, BclHelpers.NetObjectOptions options, out int dynamicTypeKey, out bool writeObject)
        {
#if FEAT_IKVM
            throw new NotSupportedException();
#else
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            dynamicTypeKey = -1;

            // length not prefixed to not move data in buffer twice just because of NetObject (will be another nested inside)
            SubItemToken token = ProtoWriter.StartSubItem(null, false, dest);

            if (value == null)
            {
                // null handling
                writeObject = false;
                return(token);
            }

            // even root object can be wrapped with collection
            // so it's not true root
            writeObject = true;
            if ((options & BclHelpers.NetObjectOptions.AsReference) != 0)
            {
                bool existing;
                int  objectKey = dest.NetCache.AddObjectKey(value, out existing);
                ProtoWriter.WriteFieldHeader(existing ? FieldExistingObjectKey : FieldNewObjectKey, WireType.Variant, dest);
                ProtoWriter.WriteInt32(objectKey, dest);
                if (existing)
                {
                    writeObject = false;
                }
            }

            if (writeObject)
            {
                if ((options & BclHelpers.NetObjectOptions.DynamicType) != 0)
                {
                    bool existing;
                    Type type = value.GetType();

                    dynamicTypeKey = dest.GetTypeKey(ref type);
                    int typeRefKey = dest.NetCache.AddObjectKey(type, out existing);
                    ProtoWriter.WriteFieldHeader(existing ? FieldExistingTypeKey : FieldNewTypeKey, WireType.Variant, dest);
                    ProtoWriter.WriteInt32(typeRefKey, dest);
                    if (!existing)
                    {
                        ProtoWriter.WriteFieldHeader(FieldTypeName, WireType.String, dest);
                        ProtoWriter.WriteString(dest.SerializeType(type), dest);
                    }
                }

                // do nothing, write will be outside
                ProtoWriter.WriteFieldHeaderBegin((options & BclHelpers.NetObjectOptions.WriteAsLateReference) != 0 ? FieldLateReferenceObject : FieldObject, dest);
            }
            return(token);
#endif
        }
Example #5
0
        // this method is split because we need to insert our implementation inside and it's hard to deal with delegates in emit

        public static void ReadNetObject_EndWithNoteNewObject(object value, ProtoReader source, object oldValue, Type type, int newObjectKey, int newTypeRefKey, BclHelpers.NetObjectOptions options, SubItemToken token)
        {
            ReadNetObject_NoteNewObject(value, source, oldValue, type, newObjectKey, newTypeRefKey, options);
            ProtoReader.EndSubItem(token, source);
        }
Example #6
0
        /// <summary>
        /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc.
        /// </summary>
        public static SubItemToken ReadNetObject_Start(ref object value, ProtoReader source, ref Type type, BclHelpers.NetObjectOptions options, out bool isDynamic, out bool isLateReference, ref int typeKey, out int newObjectKey, out int newTypeRefKey, out bool shouldEnd)
        {
#if FEAT_IKVM
            throw new NotSupportedException();
#else
            shouldEnd = false;

            newObjectKey    = -1;
            newTypeRefKey   = -1;
            isDynamic       = false;
            isLateReference = false;

            SubItemToken token = ProtoReader.StartSubItem(source);

            int fieldNumber;
            if ((fieldNumber = source.ReadFieldHeader()) == 0)
            {
                // null handling
                value = null;
                return(token);
            }
            do
            {
                int tmp;
                switch (fieldNumber)
                {
                case FieldExistingObjectKey:
                    tmp   = source.ReadInt32();
                    value = source.NetCache.GetKeyedObject(tmp);
                    break;

                case FieldNewObjectKey:
                    newObjectKey = source.ReadInt32();
                    break;

                case FieldExistingTypeKey:
                    tmp     = source.ReadInt32();
                    type    = (Type)source.NetCache.GetKeyedObject(tmp);
                    typeKey = source.GetTypeKey(ref type);
                    break;

                case FieldNewTypeKey:
                    newTypeRefKey = source.ReadInt32();
                    break;

                case FieldTypeName:
                    string typeName = source.ReadString();
                    type = source.DeserializeType(typeName);
                    if (type == null)
                    {
                        throw new ProtoException("Unable to resolve type: " + typeName + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)");
                    }
                    typeKey   = source.GetTypeKey(ref type);
                    isDynamic = true;
                    break;

                case FieldLateReferenceObject:
                case FieldObject:
                    if (fieldNumber == FieldLateReferenceObject)
                    {
                        isLateReference = true;
                    }
                    shouldEnd = true;
                    bool wasNull = value == null;
                    bool lateSet = wasNull && ((options & BclHelpers.NetObjectOptions.LateSet) != 0);
                    if (newObjectKey >= 0 && !lateSet)
                    {
                        if (value == null)
                        {
                            source.TrapNextObject(newObjectKey);
                        }
                        else
                        {
                            source.NetCache.SetKeyedObject(newObjectKey, value);
                        }
                        if (newTypeRefKey >= 0)
                        {
                            source.NetCache.SetKeyedObject(newTypeRefKey, type);
                        }
                    }
                    return(token);

                default:
                    source.SkipField();
                    break;
                }
            } while ((fieldNumber = source.ReadFieldHeader()) > 0);
            return(token);
#endif
        }