Skip to content

Commit 8784083

Browse files
committed
Add F# collection support.
This commit add FSharpList<T>, FSharpSet<T> and FSharpMap<TKey, T> support as Immutable Collections support.
1 parent fc6e12c commit 8784083

10 files changed

Lines changed: 555 additions & 3 deletions

File tree

Sync.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<Exclude Path="Serialization\CollectionSerializers\ReadOnlyDictionaryMessagePackSerializer`3.cs" />
88
<Exclude Path="Serialization\DefaultSerializers\AbstractReadOnlyCollectionMessagePackSerializer`2.cs" />
99
<Exclude Path="Serialization\DefaultSerializers\AbstractReadOnlyDictionaryMessagePackSerializer`3.cs" />
10+
<Exclude Path="Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs" />
11+
<Exclude Path="Serialization\DefaultSerializers\FSharpMapSerializer`3.cs" />
1012
<Exclude Path="Serialization\DefaultSerializers\ImmutableCollectionSerializer`2.cs" />
1113
<Exclude Path="Serialization\DefaultSerializers\ImmutableDictionarySerializer`3.cs" />
1214
<Exclude Path="Serialization\DefaultSerializers\ImmutableStackSerializer`2.cs" />
@@ -105,6 +107,8 @@
105107
<Exclude Path="Serialization\CollectionSerializers\DictionarySerializerBase`3.cs" />
106108
<Exclude Path="Serialization\CollectionSerializers\ReadOnlyCollectionMessagePackSerializer`2.cs" />
107109
<Exclude Path="Serialization\CollectionSerializers\ReadOnlyDictionaryMessagePackSerializer`3.cs" />
110+
<Exclude Path="Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs" />
111+
<Exclude Path="Serialization\DefaultSerializers\FSharpMapSerializer`3.cs" />
108112
<Exclude Path="Serialization\DefaultSerializers\ImmutableCollectionSerializer`2.cs" />
109113
<Exclude Path="Serialization\DefaultSerializers\ImmutableDictionarySerializer`3.cs" />
110114
<Exclude Path="Serialization\DefaultSerializers\ImmutableStackSerializer`2.cs" />
@@ -144,6 +148,8 @@
144148
<Exclude Path="Serialization\CollectionSerializers\ReadOnlyDictionaryMessagePackSerializer`3.cs" />
145149
<Exclude Path="Serialization\DefaultSerializers\AbstractReadOnlyCollectionMessagePackSerializer`2.cs" />
146150
<Exclude Path="Serialization\DefaultSerializers\AbstractReadOnlyDictionaryMessagePackSerializer`3.cs" />
151+
<Exclude Path="Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs" />
152+
<Exclude Path="Serialization\DefaultSerializers\FSharpMapSerializer`3.cs" />
147153
<Exclude Path="Serialization\DefaultSerializers\ImmutableCollectionSerializer`2.cs" />
148154
<Exclude Path="Serialization\DefaultSerializers\ImmutableDictionarySerializer`3.cs" />
149155
<Exclude Path="Serialization\DefaultSerializers\ImmutableStackSerializer`2.cs" />

src/MsgPack.Net45/MsgPack.Net45.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@
428428
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs">
429429
<Link>Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs</Link>
430430
</Compile>
431+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs">
432+
<Link>Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs</Link>
433+
</Compile>
434+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpMapSerializer`3.cs">
435+
<Link>Serialization\DefaultSerializers\FSharpMapSerializer`3.cs</Link>
436+
</Compile>
431437
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\GenericSerializer.cs">
432438
<Link>Serialization\DefaultSerializers\GenericSerializer.cs</Link>
433439
</Compile>

src/MsgPack.Silverlight.WindowsPhone/MsgPack.Silverlight.WindowsPhone.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@
386386
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs">
387387
<Link>Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs</Link>
388388
</Compile>
389+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs">
390+
<Link>Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs</Link>
391+
</Compile>
392+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpMapSerializer`3.cs">
393+
<Link>Serialization\DefaultSerializers\FSharpMapSerializer`3.cs</Link>
394+
</Compile>
389395
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\GenericSerializer.cs">
390396
<Link>Serialization\DefaultSerializers\GenericSerializer.cs</Link>
391397
</Compile>

src/MsgPack.Uwp/MsgPack.Uwp.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,12 @@
383383
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs">
384384
<Link>Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs</Link>
385385
</Compile>
386+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs">
387+
<Link>Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs</Link>
388+
</Compile>
389+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpMapSerializer`3.cs">
390+
<Link>Serialization\DefaultSerializers\FSharpMapSerializer`3.cs</Link>
391+
</Compile>
386392
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\GenericSerializer.cs">
387393
<Link>Serialization\DefaultSerializers\GenericSerializer.cs</Link>
388394
</Compile>

src/MsgPack.Xamarin.Android/MsgPack.Xamarin.Android.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@
314314
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\DefaultSerializers.cs">
315315
<Link>Serialization\DefaultSerializers\DefaultSerializers.cs</Link>
316316
</Compile>
317+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs">
318+
<Link>Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs</Link>
319+
</Compile>
320+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpMapSerializer`3.cs">
321+
<Link>Serialization\DefaultSerializers\FSharpMapSerializer`3.cs</Link>
322+
</Compile>
317323
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\GenericSerializer.cs">
318324
<Link>Serialization\DefaultSerializers\GenericSerializer.cs</Link>
319325
</Compile>

src/MsgPack.Xamarin.iOS/MsgPack.Xamarin.iOS.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@
311311
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\DefaultSerializers.cs">
312312
<Link>Serialization\DefaultSerializers\DefaultSerializers.cs</Link>
313313
</Compile>
314+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs">
315+
<Link>Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs</Link>
316+
</Compile>
317+
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\FSharpMapSerializer`3.cs">
318+
<Link>Serialization\DefaultSerializers\FSharpMapSerializer`3.cs</Link>
319+
</Compile>
314320
<Compile Include="..\MsgPack\Serialization\DefaultSerializers\GenericSerializer.cs">
315321
<Link>Serialization\DefaultSerializers\GenericSerializer.cs</Link>
316322
</Compile>

src/MsgPack/MsgPack.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@
240240
<Compile Include="Serialization\DefaultSerializers\DateTimeOffsetMessagePackSerializer.cs" />
241241
<Compile Include="Serialization\DefaultSerializers\DateTimeOffsetMessagePackSerializerProvider.cs" />
242242
<Compile Include="Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs" />
243+
<Compile Include="Serialization\DefaultSerializers\FSharpCollectionSerializer`2.cs" />
244+
<Compile Include="Serialization\DefaultSerializers\FSharpMapSerializer`3.cs" />
243245
<Compile Include="Serialization\DefaultSerializers\InternalDateTimeExtensions.cs" />
244246
<Compile Include="Serialization\DefaultSerializers\MultidimensionalArraySerializer`1.cs">
245247
<SubType>Code</SubType>
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#region -- License Terms --
2+
//
3+
// MessagePack for CLI
4+
//
5+
// Copyright (C) 2016 FUJIWARA, Yusuke
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
#endregion -- License Terms --
20+
21+
#if UNITY_5 || UNITY_STANDALONE || UNITY_WEBPLAYER || UNITY_WII || UNITY_IPHONE || UNITY_ANDROID || UNITY_PS3 || UNITY_XBOX360 || UNITY_FLASH || UNITY_BKACKBERRY || UNITY_WINRT
22+
#define UNITY
23+
#endif
24+
25+
using System;
26+
using System.Collections.Generic;
27+
using System.Globalization;
28+
using System.Linq;
29+
#if FEATURE_TAP
30+
using System.Threading;
31+
using System.Threading.Tasks;
32+
#endif // FEATURE_TAP
33+
34+
namespace MsgPack.Serialization.DefaultSerializers
35+
{
36+
[Preserve( AllMembers = true )]
37+
internal sealed class FSharpCollectionSerializer<T, TItem> : MessagePackSerializer<T>
38+
where T : IEnumerable<TItem>
39+
{
40+
private readonly Func<TItem[], T> _factory;
41+
42+
private static Func<TItem[], T> FindFactory( string factoryTypeName )
43+
{
44+
var factoryType =
45+
typeof( T ).GetAssembly().GetType(
46+
typeof( T ).Namespace + "." + factoryTypeName
47+
);
48+
49+
if ( factoryType == null )
50+
{
51+
return
52+
_ =>
53+
{
54+
throw new NotSupportedException(
55+
String.Format(
56+
CultureInfo.CurrentCulture,
57+
"Cannot find {1}. '{0}' may not be an fsharp collection.",
58+
typeof( T ).AssemblyQualifiedName,
59+
factoryTypeName
60+
)
61+
);
62+
};
63+
}
64+
65+
var methods =
66+
factoryType
67+
.GetMethods()
68+
.Where(
69+
m =>
70+
m.IsStatic
71+
&& m.IsPublic
72+
&& m.IsGenericMethod
73+
&& m.Name == "OfSeq"
74+
&& m.GetParameters().Length == 1
75+
);
76+
77+
var method = methods.FirstOrDefault();
78+
79+
if ( method == null )
80+
{
81+
return
82+
_ =>
83+
{
84+
throw new NotSupportedException(
85+
String.Format(
86+
CultureInfo.CurrentCulture,
87+
"'{0}' does not have OfSeq({1}) public static method.",
88+
factoryType.AssemblyQualifiedName,
89+
typeof( IEnumerable<TItem> )
90+
)
91+
);
92+
};
93+
}
94+
95+
var result = method.MakeGenericMethod( typeof( TItem ) );
96+
#if !UNITY
97+
return result.CreateDelegate( typeof( Func<IEnumerable<TItem>, T> ) ) as Func<IEnumerable<TItem>, T>;
98+
#else
99+
return Delegate.CreateDelegate( typeof( Func<IEnumerable<TItem>, T> ), result ) as Func<IEnumerable<TItem>, T>;
100+
#endif // !UNITY
101+
}
102+
103+
private readonly MessagePackSerializer<TItem> _itemSerializer;
104+
105+
public FSharpCollectionSerializer( SerializationContext ownerContext, PolymorphismSchema itemsSchema, string factoryTypeName )
106+
: base( ownerContext )
107+
{
108+
this._itemSerializer = ownerContext.GetSerializer<TItem>( itemsSchema );
109+
this._factory = FindFactory( factoryTypeName );
110+
}
111+
112+
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Validated by caller in base class" )]
113+
protected internal override void PackToCore( Packer packer, T objectTree )
114+
{
115+
packer.PackArrayHeader( objectTree.Count() );
116+
117+
foreach ( var item in objectTree )
118+
{
119+
this._itemSerializer.PackTo( packer, item );
120+
}
121+
}
122+
123+
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Validated by caller in base class" )]
124+
protected internal override T UnpackFromCore( Unpacker unpacker )
125+
{
126+
if ( !unpacker.IsArrayHeader )
127+
{
128+
SerializationExceptions.ThrowIsNotArrayHeader( unpacker );
129+
}
130+
131+
var buffer = new TItem[ UnpackHelpers.GetItemsCount( unpacker ) ];
132+
133+
using ( var subTreeUnpacker = unpacker.ReadSubtree() )
134+
{
135+
for ( int i = 0; i < buffer.Length; i++ )
136+
{
137+
if ( !subTreeUnpacker.Read() )
138+
{
139+
SerializationExceptions.ThrowUnexpectedEndOfStream( unpacker );
140+
}
141+
142+
buffer[ i ] = this._itemSerializer.UnpackFrom( subTreeUnpacker );
143+
}
144+
}
145+
146+
return this._factory( buffer );
147+
}
148+
149+
protected internal override void UnpackToCore( Unpacker unpacker, T collection )
150+
{
151+
throw new NotSupportedException(
152+
String.Format(
153+
CultureInfo.CurrentCulture,
154+
"Unable to unpack items to existing immutable collection '{0}'.",
155+
typeof( T )
156+
)
157+
);
158+
}
159+
160+
#if FEATURE_TAP
161+
162+
protected internal override async Task PackToAsyncCore( Packer packer, T objectTree, CancellationToken cancellationToken )
163+
{
164+
await packer.PackArrayHeaderAsync( objectTree.Count(), cancellationToken ).ConfigureAwait( false );
165+
166+
foreach ( var item in objectTree )
167+
{
168+
await this._itemSerializer.PackToAsync( packer, item, cancellationToken ).ConfigureAwait( false );
169+
}
170+
}
171+
172+
protected internal override async Task<T> UnpackFromAsyncCore( Unpacker unpacker, CancellationToken cancellationToken )
173+
{
174+
if ( !unpacker.IsArrayHeader )
175+
{
176+
SerializationExceptions.ThrowIsNotArrayHeader( unpacker );
177+
}
178+
179+
var buffer = new TItem[ UnpackHelpers.GetItemsCount( unpacker ) ];
180+
181+
using ( var subTreeUnpacker = unpacker.ReadSubtree() )
182+
{
183+
for ( int i = 0; i < buffer.Length; i++ )
184+
{
185+
if ( !await subTreeUnpacker.ReadAsync( cancellationToken ).ConfigureAwait( false ) )
186+
{
187+
SerializationExceptions.ThrowUnexpectedEndOfStream( unpacker );
188+
}
189+
190+
buffer[ i ] = await this._itemSerializer.UnpackFromAsync( subTreeUnpacker, cancellationToken ).ConfigureAwait( false );
191+
}
192+
}
193+
194+
return this._factory( buffer );
195+
}
196+
197+
protected internal override Task UnpackToAsyncCore( Unpacker unpacker, T collection, CancellationToken cancellationToken )
198+
{
199+
throw new NotSupportedException(
200+
String.Format(
201+
CultureInfo.CurrentCulture,
202+
"Unable to unpack items to existing immutable collection '{0}'.",
203+
typeof( T )
204+
)
205+
);
206+
}
207+
208+
#endif // FEATURE_TAP
209+
210+
}
211+
}

0 commit comments

Comments
 (0)