Exemplo n.º 1
0
 public RubyToken Decode(string file, RubyDecoderOptions options)
 {
     using (var stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
     {
         return(Decode(stream, options));
     }
 }
Exemplo n.º 2
0
        public RubyToken Decode(Stream stream, RubyDecoderOptions options)
        {
            using (var reader = new BinaryReader(stream))
            {
                if (reader.ReadInt16() == 0x0804)
                {
                    return(ReadEntry(new ReadContext
                    {
                        Reader = reader
                    },
                                     options ?? new RubyDecoderOptions()));
                }
            }

            return(null);
        }
Exemplo n.º 3
0
        internal static RubyToken ReadEntry(ReadContext context, RubyDecoderOptions options)
        {
            RubyClass  rubyClass;
            int        fieldCount;
            RubyObject objectEntry;

            var type = (RubyType)context.Reader.ReadByte();

            switch (type)
            {
            case RubyType.Nil:
                return(new RubyValue((object)null));

            case RubyType.TypeLink:
                var dataId = (int)ReadNumber(context);
                if (context.Data.Count > dataId)
                {
                    return(context.Data[dataId]);
                }
                else
                {
                    throw new Exception("Failed to locate linked data");
                }

            case RubyType.Array:
                var length     = (int)ReadNumber(context);
                var arrayEntry = new RubyArray
                {
                    Array = new List <RubyToken>(length)
                };
                context.Data.Add(arrayEntry);

                for (var index = 0; index < length; index++)
                {
                    arrayEntry.Array.Add(ReadEntry(context, options));
                }

                return(arrayEntry);

            case RubyType.Object:
                rubyClass   = ReadSymbolDefinition(context);
                fieldCount  = (int)ReadNumber(context);
                objectEntry = new RubyObject
                {
                    RubyClass  = rubyClass,
                    Properties = new Dictionary <string, RubyToken>(fieldCount)
                };
                context.Data.Add(objectEntry);

                for (var fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
                {
                    var keySymbol = ReadSymbolDefinition(context);
                    var value     = ReadEntry(context, options);
                    objectEntry.Properties.Add(keySymbol.Name.TrimStart('@'), value);
                }

                return(objectEntry);

            case RubyType.UserDefined:
                rubyClass = ReadSymbolDefinition(context);
                if (options.UserDecoders != null && options.UserDecoders.TryGetValue(rubyClass.Name, out var decoder))
                {
                    ReadNumber(context);
                    var userDefinedEntry = decoder(context.Reader);
                    userDefinedEntry.RubyClass = rubyClass;
                    context.Data.Add(userDefinedEntry);
                    return(userDefinedEntry);
                }
                else
                {
                    throw new Exception($"User defined type not handled: {rubyClass.Name}");
                }

            case RubyType.Hash:
                fieldCount  = (int)ReadNumber(context);
                objectEntry = new RubyObject
                {
                    RubyClass = new RubyClass {
                        Name = "encoder:Hash"
                    },
                    Properties = new Dictionary <string, RubyToken>(fieldCount)
                };
                context.Data.Add(objectEntry);

                for (var fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
                {
                    var key   = ReadEntry(context, options);
                    var value = ReadEntry(context, options);
                    objectEntry.Properties.Add(key.ToString(), value);
                }

                return(objectEntry);

            case RubyType.Number:
                return(new RubyValue(ReadNumber(context)));

            case RubyType.Decimal:
                var rubyFloat = new RubyValue(ReadFloat(context));
                context.Data.Add(rubyFloat);
                return(rubyFloat);

            case RubyType.String:
                var stringEntry = ReadStringValue(context);
                context.Data.Add(stringEntry);
                return(stringEntry);

            case RubyType.True:
                return(new RubyValue(true));

            case RubyType.False:
                return(new RubyValue(false));

            default:
                throw new Exception($"Unknown type: {type}");
            }
        }