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