Exemplo n.º 1
0
        public void Various_Bool()
        {
            // note: this test was ported from RserveCLI.  Not in the typical Arrange/Act/Assert format
            using (var service = new Rservice())
            {
                var sexpTrue  = new SexpArrayBool(true);
                var sexpFalse = new SexpArrayBool(false);
                var sexpNa    = new SexpArrayBool(( bool? )null);

                // ReSharper disable EqualExpressionComparison
                Assert.True(sexpTrue.Equals(sexpTrue));
                Assert.True(sexpFalse.Equals(sexpFalse));
                Assert.True(sexpNa.Equals(sexpNa));

                // ReSharper restore EqualExpressionComparison
                Assert.True(!sexpTrue.Equals(sexpFalse));
                Assert.True(!sexpTrue.Equals(sexpNa));
                Assert.True(sexpTrue.Equals(true));
                Assert.True(sexpFalse.Equals(false));
                Assert.True(!sexpNa.Equals(true));
                Assert.True(!sexpNa.Equals(false));
                foreach (var a in new Sexp[] { sexpTrue, sexpFalse, sexpNa })
                {
                    Assert.True(!a.Equals(new SexpNull()));
                }

                service.RConnection["x.bool"] = Sexp.Make(true);
            }
        }
Exemplo n.º 2
0
        public void Indexer_SetWithNonSexpArrayDate_ThrowsNotSupportedException()
        {
            // Arrange
            var sexp1 = new SexpArrayDate(new DateTime(2004, 01, 23));
            var sexp2 = new SexpArrayDate(new[] { new DateTime(2004, 01, 23), new DateTime(2005, 01, 23), new DateTime(2007, 03, 12) });

            // Act & Assert
            Assert.Throws <NotSupportedException>(() => sexp1[0] = new SexpArrayBool(false));
            Assert.Throws <NotSupportedException>(() => sexp2[0] = new SexpArrayString("asdf"));
        }
Exemplo n.º 3
0
        public void Various_ArrayBool()
        {
            // note: this test was ported from RserveCLI.  Not in the typical Arrange/Act/Assert format
            using (var service = new Rservice())
            {
                var testvals = new bool?[] { true, false, null };
                var x1       = new SexpArrayBool(testvals);

                Assert.Equal(testvals.Length, x1.Count);

                service.RConnection["x1"] = x1;

                for (int i = 0; i < x1.Count; i++)
                {
                    Assert.Equal(new SexpArrayBool(testvals[i]).AsBool, x1[i].AsBool);
                }

                service.RConnection.Eval("x2 <- as.logical(c(TRUE,FALSE,NA))");
                var x2 = service.RConnection["x2"];

                Assert.Equal(x1.Count, x2.Count);

                for (int i = 0; i < x1.Count; i++)
                {
                    if (x1[i].IsNa)
                    {
                        Assert.True(x2[i].IsNa);
                    }
                    else
                    {
                        Assert.Equal(x1[i].AsBool, x2[i].AsBool);
                    }
                }

                var equals = service.RConnection["x1 == x2"];

                Assert.Equal(x1.Count, equals.Count);

                for (int i = 0; i < x1.Count; i++)
                {
                    if (!x1[i].IsNa)
                    {
                        Assert.True(( bool )(equals[i].AsBool), equals.ToString());
                    }
                }

                Assert.Equal(x1.IndexOf(Sexp.Make(false)), 1);

                x1.AsList[0] = false;
                Assert.Equal(x1[0].AsBool, false);
            }
        }
        public void AsBools_WriteSexpArrayBoolToRAndReadBack_ReturnsArrayOfNullableBools()
        {
            using ( var service = new Rservice() )
            {
                // Arrange
                Sexp bool1 = new SexpArrayBool();
                Sexp bool2 = new SexpArrayBool( true );
                Sexp bool3 = new SexpArrayBool( false );
                Sexp bool4 = new SexpArrayBool( ( bool? )null );
                Sexp bool5 = new SexpArrayBool( new bool?[] { true } );
                Sexp bool6 = new SexpArrayBool( new bool?[] { false } );
                Sexp bool7 = new SexpArrayBool( new bool?[] { null } );
                Sexp bool8 = new SexpArrayBool( new bool?[] { true , null , false } );
                Sexp bool9 = new SexpArrayBool( new bool?[] { true , false , null , true , false , null } );
                bool9.Attributes.Add( "dim" , Sexp.Make( new[] { 2 , 3 } ) );

                // Act
                service.RConnection[ "bool1" ] = bool1;
                service.RConnection[ "bool2" ] = bool2;
                service.RConnection[ "bool3" ] = bool3;
                service.RConnection[ "bool4" ] = bool4;
                service.RConnection[ "bool5" ] = bool5;
                service.RConnection[ "bool6" ] = bool6;
                service.RConnection[ "bool7" ] = bool7;
                service.RConnection[ "bool8" ] = bool8;
                service.RConnection[ "bool9" ] = bool9;
                bool1 = service.RConnection[ "bool1" ];
                bool2 = service.RConnection[ "bool2" ];
                bool3 = service.RConnection[ "bool3" ];
                bool4 = service.RConnection[ "bool4" ];
                bool5 = service.RConnection[ "bool5" ];
                bool6 = service.RConnection[ "bool6" ];
                bool7 = service.RConnection[ "bool7" ];
                bool8 = service.RConnection[ "bool8" ];
                bool9 = service.RConnection[ "bool9" ];

                // Assert
                Assert.Equal( new bool?[] { } , bool1.AsBools );
                Assert.Equal( new bool?[] { true } , bool2.AsBools );
                Assert.Equal( new bool?[] { false } , bool3.AsBools );
                Assert.Equal( new bool?[] { null } , bool4.AsBools );
                Assert.Equal( new bool?[] { true } , bool5.AsBools );
                Assert.Equal( new bool?[] { false } , bool6.AsBools );
                Assert.Equal( new bool?[] { null } , bool7.AsBools );
                Assert.Equal( new bool?[] { true , null , false } , bool8.AsBools );
                Assert.Equal( new bool?[] { true , false , null , true , false , null } , bool9.AsBools );

            }
        }
Exemplo n.º 5
0
        public void AsBools_WriteSexpArrayBoolToRAndReadBack_ReturnsArrayOfNullableBools()
        {
            using (var service = new Rservice())
            {
                // Arrange
                Sexp bool1 = new SexpArrayBool();
                Sexp bool2 = new SexpArrayBool(true);
                Sexp bool3 = new SexpArrayBool(false);
                Sexp bool4 = new SexpArrayBool(( bool? )null);
                Sexp bool5 = new SexpArrayBool(new bool?[] { true });
                Sexp bool6 = new SexpArrayBool(new bool?[] { false });
                Sexp bool7 = new SexpArrayBool(new bool?[] { null });
                Sexp bool8 = new SexpArrayBool(new bool?[] { true, null, false });
                Sexp bool9 = new SexpArrayBool(new bool?[] { true, false, null, true, false, null });
                bool9.Attributes.Add("dim", Sexp.Make(new[] { 2, 3 }));

                // Act
                service.RConnection["bool1"] = bool1;
                service.RConnection["bool2"] = bool2;
                service.RConnection["bool3"] = bool3;
                service.RConnection["bool4"] = bool4;
                service.RConnection["bool5"] = bool5;
                service.RConnection["bool6"] = bool6;
                service.RConnection["bool7"] = bool7;
                service.RConnection["bool8"] = bool8;
                service.RConnection["bool9"] = bool9;
                bool1 = service.RConnection["bool1"];
                bool2 = service.RConnection["bool2"];
                bool3 = service.RConnection["bool3"];
                bool4 = service.RConnection["bool4"];
                bool5 = service.RConnection["bool5"];
                bool6 = service.RConnection["bool6"];
                bool7 = service.RConnection["bool7"];
                bool8 = service.RConnection["bool8"];
                bool9 = service.RConnection["bool9"];

                // Assert
                Assert.Equal(new bool?[] { }, bool1.AsBools);
                Assert.Equal(new bool?[] { true }, bool2.AsBools);
                Assert.Equal(new bool?[] { false }, bool3.AsBools);
                Assert.Equal(new bool?[] { null }, bool4.AsBools);
                Assert.Equal(new bool?[] { true }, bool5.AsBools);
                Assert.Equal(new bool?[] { false }, bool6.AsBools);
                Assert.Equal(new bool?[] { null }, bool7.AsBools);
                Assert.Equal(new bool?[] { true, null, false }, bool8.AsBools);
                Assert.Equal(new bool?[] { true, false, null, true, false, null }, bool9.AsBools);
            }
        }
Exemplo n.º 6
0
        public void Equals_ComparedToObjectOfDifferentType_ReturnsFalse()
        {
            // Arrange
            var value1 = new SexpArrayDouble(new[] { 2.3, double.NaN, 4 });
            var value2 = new SexpArrayBool(true);
            var value3 = new SexpArrayInt(new[] { 1, 3 });

            // Act & Assert

            // ReSharper disable RedundantCast
            Assert.False(value1.Equals(value2));
            Assert.False(value1.Equals(( object )value2));
            Assert.False(value1.Equals(value3));
            Assert.False(value1.Equals(( object )value3));
            // ReSharper restore RedundantCast
        }
Exemplo n.º 7
0
        public void Command_AssignAndEvalLargeSexpArrayBool_ProperlyEncodesAndDecodesArrayOfBoolean()
        {
            using (var service = new Rservice())
            {
                // Arrange
                var random = new Random();

                const int count             = 25497500;
                var       sexpBool1ToEncode = new SexpArrayBool(Enumerable.Range(0, count).Select(x => { var y = random.Next(1, 4); return(y == 1 ? true : y == 2 ? false : ( bool? )null); }));
                var       sexpBool2ToEncode = new SexpArrayBool(Enumerable.Range(0, count + 1).Select(x => { var y = random.Next(1, 4); return(y == 1 ? true : y == 2 ? false : ( bool? )null); }));
                var       sexpBool3ToEncode = new SexpArrayBool(Enumerable.Range(0, count + 3).Select(x => { var y = random.Next(1, 4); return(y == 1 ? true : y == 2 ? false : ( bool? )null); }));
                var       sexpBool4ToEncode = new SexpArrayBool(Enumerable.Range(0, count + 4).Select(x => { var y = random.Next(1, 4); return(y == 1 ? true : y == 2 ? false : ( bool? )null); }));

                // Act
                service.RConnection["bools1"] = sexpBool1ToEncode;
                service.RConnection["bools2"] = sexpBool2ToEncode;
                service.RConnection["bools3"] = sexpBool3ToEncode;
                service.RConnection["bools4"] = sexpBool4ToEncode;

                Sexp sexpBool1ToDecoded = service.RConnection["bools1"];
                Sexp sexpBool2ToDecoded = service.RConnection["bools2"];
                Sexp sexpBool3ToDecoded = service.RConnection["bools3"];
                Sexp sexpBool4ToDecoded = service.RConnection["bools4"];

                // Assert
                Assert.IsType <SexpArrayBool>(sexpBool1ToDecoded);
                Assert.IsType <SexpArrayBool>(sexpBool2ToDecoded);
                Assert.IsType <SexpArrayBool>(sexpBool3ToDecoded);
                Assert.IsType <SexpArrayBool>(sexpBool4ToDecoded);

                Assert.True(sexpBool1ToEncode.Values.SequenceEqual(sexpBool1ToDecoded.Values));
                Assert.True(sexpBool2ToEncode.Values.SequenceEqual(sexpBool2ToDecoded.Values));
                Assert.True(sexpBool3ToEncode.Values.SequenceEqual(sexpBool3ToDecoded.Values));
                Assert.True(sexpBool4ToEncode.Values.SequenceEqual(sexpBool4ToDecoded.Values));
            }
        }
Exemplo n.º 8
0
        public void Command_AssignAndEvalLargeSexpArrayBool_ProperlyEncodesAndDecodesArrayOfBoolean()
        {
            using ( var service = new Rservice() )
            {
                // Arrange
                var random = new Random();

                const int count = 25497500;
                var sexpBool1ToEncode = new SexpArrayBool( Enumerable.Range( 0 , count ).Select( x => { var y = random.Next( 1 , 4 ); return ( y == 1 ? true : y == 2 ? false : ( bool? )null ); } ) );
                var sexpBool2ToEncode = new SexpArrayBool( Enumerable.Range( 0 , count + 1 ).Select( x => { var y = random.Next( 1 , 4 ); return ( y == 1 ? true : y == 2 ? false : ( bool? )null ); } ) );
                var sexpBool3ToEncode = new SexpArrayBool( Enumerable.Range( 0 , count + 3 ).Select( x => { var y = random.Next( 1 , 4 ); return ( y == 1 ? true : y == 2 ? false : ( bool? )null ); } ) );
                var sexpBool4ToEncode = new SexpArrayBool( Enumerable.Range( 0 , count + 4 ).Select( x => { var y = random.Next( 1 , 4 ); return ( y == 1 ? true : y == 2 ? false : ( bool? )null ); } ) );

                // Act
                service.RConnection[ "bools1" ] = sexpBool1ToEncode;
                service.RConnection[ "bools2" ] = sexpBool2ToEncode;
                service.RConnection[ "bools3" ] = sexpBool3ToEncode;
                service.RConnection[ "bools4" ] = sexpBool4ToEncode;

                Sexp sexpBool1ToDecoded = service.RConnection[ "bools1" ];
                Sexp sexpBool2ToDecoded = service.RConnection[ "bools2" ];
                Sexp sexpBool3ToDecoded = service.RConnection[ "bools3" ];
                Sexp sexpBool4ToDecoded = service.RConnection[ "bools4" ];

                // Assert
                Assert.IsType<SexpArrayBool>( sexpBool1ToDecoded );
                Assert.IsType<SexpArrayBool>( sexpBool2ToDecoded );
                Assert.IsType<SexpArrayBool>( sexpBool3ToDecoded );
                Assert.IsType<SexpArrayBool>( sexpBool4ToDecoded );

                Assert.True( sexpBool1ToEncode.Values.SequenceEqual( sexpBool1ToDecoded.Values ) );
                Assert.True( sexpBool2ToEncode.Values.SequenceEqual( sexpBool2ToDecoded.Values ) );
                Assert.True( sexpBool3ToEncode.Values.SequenceEqual( sexpBool3ToDecoded.Values ) );
                Assert.True( sexpBool4ToEncode.Values.SequenceEqual( sexpBool4ToDecoded.Values ) );
            }
        }
        public void Equals_ComparedToObjectOfDifferentType_ReturnsFalse()
        {
            // Arrange
            var value1 = new SexpArrayDouble( new[] { 2.3 , double.NaN , 4 } );
            var value2 = new SexpArrayBool( true );
            var value3 = new SexpArrayInt( new[] { 1 , 3 } );

            // Act & Assert

            // ReSharper disable RedundantCast
            Assert.False( value1.Equals( value2 ) );
            Assert.False( value1.Equals( ( object )value2 ) );
            Assert.False( value1.Equals( value3 ) );
            Assert.False( value1.Equals( ( object )value3 ) );
            // ReSharper restore RedundantCast
        }
Exemplo n.º 10
0
        public void Various_ArrayBool()
        {
            // note: this test was ported from RserveCLI.  Not in the typical Arrange/Act/Assert format
            using ( var service = new Rservice() )
            {
                var testvals = new bool?[] { true , false , null };
                var x1 = new SexpArrayBool( testvals );

                Assert.Equal( testvals.Length , x1.Count );

                service.RConnection[ "x1" ] = x1;

                for ( int i = 0 ; i < x1.Count ; i++ )
                {
                    Assert.Equal( new SexpArrayBool( testvals[ i ] ).AsBool , x1[ i ].AsBool );
                }

                service.RConnection.Eval( "x2 <- as.logical(c(TRUE,FALSE,NA))" );
                var x2 = service.RConnection[ "x2" ];

                Assert.Equal( x1.Count , x2.Count );

                for ( int i = 0 ; i < x1.Count ; i++ )
                {
                    if ( x1[ i ].IsNa )
                    {
                        Assert.True( x2[ i ].IsNa );
                    }
                    else
                    {
                        Assert.Equal( x1[ i ].AsBool , x2[ i ].AsBool );
                    }
                }

                var equals = service.RConnection[ "x1 == x2" ];

                Assert.Equal( x1.Count , equals.Count );

                for ( int i = 0 ; i < x1.Count ; i++ )
                {
                    if ( !x1[ i ].IsNa )
                    {
                        Assert.True( ( bool )( equals[ i ].AsBool ) , equals.ToString() );
                    }
                }

                Assert.Equal( x1.IndexOf( Sexp.Make( false ) ) , 1 );

                x1.AsList[ 0 ] = false;
                Assert.Equal( x1[ 0 ].AsBool , false );
            }
        }
Exemplo n.º 11
0
        public void Various_Bool()
        {
            // note: this test was ported from RserveCLI.  Not in the typical Arrange/Act/Assert format
            using ( var service = new Rservice() )
            {
                var sexpTrue = new SexpArrayBool( true );
                var sexpFalse = new SexpArrayBool( false );
                var sexpNa = new SexpArrayBool( ( bool? )null );

                // ReSharper disable EqualExpressionComparison
                Assert.True( sexpTrue.Equals( sexpTrue ) );
                Assert.True( sexpFalse.Equals( sexpFalse ) );
                Assert.True( sexpNa.Equals( sexpNa ) );

                // ReSharper restore EqualExpressionComparison
                Assert.True( !sexpTrue.Equals( sexpFalse ) );
                Assert.True( !sexpTrue.Equals( sexpNa ) );
                Assert.True( sexpTrue.Equals( true ) );
                Assert.True( sexpFalse.Equals( false ) );
                Assert.True( !sexpNa.Equals( true ) );
                Assert.True( !sexpNa.Equals( false ) );
                foreach ( var a in new Sexp[] { sexpTrue , sexpFalse , sexpNa } )
                {
                    Assert.True( !a.Equals( new SexpNull() ) );
                }

                service.RConnection[ "x.bool" ] = Sexp.Make( true );
            }
        }
Exemplo n.º 12
0
        public void Indexer_SetWithNonSexpArrayDate_ThrowsNotSupportedException()
        {
            // Arrange
            var sexp1 = new SexpArrayDate( new DateTime( 2004 , 01 , 23 ) );
            var sexp2 = new SexpArrayDate( new[] { new DateTime( 2004 , 01 , 23 ) , new DateTime( 2005 , 01 , 23 ) , new DateTime( 2007 , 03 , 12 ) } );

            // Act & Assert
            Assert.Throws<NotSupportedException>( () => sexp1[ 0 ] = new SexpArrayBool( false ) );
            Assert.Throws<NotSupportedException>( () => sexp2[ 0 ] = new SexpArrayString( "asdf" ) );
        }
Exemplo n.º 13
0
        /// <summary>
        /// Decode a Qap1-encoded Sexp
        /// </summary>
        /// <param name="data">The byte stream in which the Sexp is encoded</param>
        /// <param name="start">At which index of data does the Sexp begin?</param>
        /// <returns>The decoded Sexp.</returns>
        private static Sexp DecodeSexp( byte[] data , ref long start )
        {
            // pull sexp type
            byte xt = data[ start ];

            // calculate length of payload
            var lengthBuf = new byte[ 8 ];
            Array.Copy( data , start + 1 , lengthBuf , 0 , 3 );
            start += 4;
            if ( ( xt & XtLarge ) == XtLarge )
            {
                Array.Copy( data , start , lengthBuf , 3 , 4 );
                start += 4;
                xt -= XtLarge;
            }
            var length = ( long )BitConverter.ToUInt64( lengthBuf , 0 );

            // has attributes?  process first
            SexpTaggedList attrs = null;
            if ( ( xt & XtHasAttr ) == XtHasAttr )
            {
                xt -= XtHasAttr;
                long oldstart = start;
                attrs = ( SexpTaggedList )DecodeSexp( data , ref start );
                length -= start - oldstart;
            }

            long end = start + length;
            Sexp result;

            switch ( xt )
            {
                case XtNull:
                    {
                        if ( length != 0 )
                        {
                            throw new RserveException( "Attempting to decode an SexpNull, but it is followed by data when it shouldn't be." );
                        }
                        result = new SexpNull();
                    }
                    break;
                case XtSymName:
                    {
                        // keep all characters up to the first null
                        var symnNamBuf = new byte[ length ];
                        Array.Copy( data , start , symnNamBuf , 0 , length );
                        string res = Encoding.UTF8.GetString( symnNamBuf );
                        result = new SexpSymname( res.Split( '\x00' )[ 0 ] );
                    }
                    break;
                case XtArrayInt:
                    {
                        var res = new int[ length / 4 ];
                        var intBuf = new byte[ 4 ];
                        for ( long i = 0 ; i < length ; i += 4 )
                        {
                            Array.Copy( data , start + i , intBuf , 0 , 4 );
                            res[ i / 4 ] = BitConverter.ToInt32( intBuf , 0 );
                        }

                        // is date or just an integer?
                        if ( ( attrs != null ) && ( attrs.ContainsKey( "class" ) && attrs[ "class" ].AsStrings.Contains( "Date" ) ) )
                        {
                            result = new SexpArrayDate( res );
                        }
                        else
                        {
                            result = new SexpArrayInt( res );
                        }
                    }
                    break;
                case XtArrayBool:
                    {
                        if ( length < 4 )
                        {
                            throw new RserveException( "Decoding an SexpArrayBool where data doesn't seem to contain a data length field." );
                        }
                        var boolLengthBuf = new byte[ 4 ];
                        Array.Copy( data , start , boolLengthBuf , 0 , 4 );
                        var datalength = BitConverter.ToInt32( boolLengthBuf , 0 );
                        if ( datalength > length - 4 )
                        {
                            throw new RserveException( "Decoding an SexpArrayBool where transmitted data field too short for number of entries." );
                        }

                        var res = new bool?[ datalength ];
                        for ( int i = 0 ; i < datalength ; i++ )
                        {
                            // R logical is false if 0, true if 1, and NA if 2
                            switch ( data[ start + i + 4 ] )
                            {
                                case 0:
                                    res[ i ] = false;
                                    break;
                                case 1:
                                    res[ i ] = true;
                                    break;
                                case 2:
                                    res[ i ] = null;
                                    break;
                                default:
                                    throw new RserveException( "Decoding an SexpArrayBool and found an element in the array that is not an R bool: " + data[ start + i + 4 ] );
                            }
                        }

                        result = new SexpArrayBool( res );
                    }
                    break;
                case XtArrayDouble:
                    {
                        var res = new double[ length / 8 ];
                        var doubleBuf = new byte[ 8 ];
                        for ( long i = 0 ; i < length ; i += 8 )
                        {
                            Array.Copy( data , start + i , doubleBuf , 0 , 8 );
                            res[ i / 8 ] = BitConverter.ToDouble( doubleBuf , 0 );
                        }

                        // is date or just a double?
                        if ( ( attrs != null ) && ( attrs.ContainsKey( "class" ) && attrs[ "class" ].AsStrings.Contains( "Date" ) ) )
                        {
                            result = new SexpArrayDate( res.Select( Convert.ToInt32 ) );
                        }
                        else
                        {
                            result = new SexpArrayDouble( res );
                        }
                    }
                    break;
                case XtArrayString:
                    {
                        var res = new List<string>();
                        long i = 0;
                        for ( long j = 0 ; j < length ; j++ )
                        {
                            if ( data[ start + j ] != 0 )
                            {
                                continue;
                            }

                            if ( ( j == i + 1 ) && ( data[ start + i ] == 255 ) )
                            {
                                res.Add( null );
                            }
                            else
                            {
                                if ( data[ start + i ] == 255 )
                                {
                                    i++;
                                }

                                var stringBuf = new byte[ j - i ];
                                Array.Copy( data , start + i , stringBuf , 0 , j - i );
                                res.Add( Encoding.UTF8.GetString( stringBuf ) );
                            }
                            i = j + 1;
                        }

                        result = new SexpArrayString( res );
                    }
                    break;
                case XtListNoTag:
                case XtLangNoTag:
                case XtVector:
                    result = new SexpList();
                    while ( start < end )
                    {
                        result.Add( DecodeSexp( data , ref start ) );
                    }
                    break;
                case XtLangTag:
                case XtListTag:
                    result = new SexpTaggedList();
                    while ( start < end )
                    {
                        Sexp val = DecodeSexp( data , ref start );
                        Sexp key = DecodeSexp( data , ref start );
                        result.Add( key.IsNull ? String.Empty : key.AsString , val );
                    }

                    break;
                case XtRaw:
                    {
                        var d = new byte[ length ];
                        Array.Copy( data , start , d , 0 , length );
                        result = new SexpQap1Raw( xt , d );
                    }
                    break;
                default:
                    throw new RserveException( "Cannot decode an Sexp because the type is not recognized: " + xt );
            }

            if ( start > end )
            {
                throw new RserveException( "When decoding an Sexp, more data consumed than provided." );
            }

            start = end;
            if ( attrs != null )
            {
                foreach ( var a in attrs.AsSexpDictionary )
                {
                    result.Attributes.Add( a.Key , a.Value );
                }
            }

            return result;
        }