@@ -85,26 +85,38 @@ type converter struct {
85
85
customToAny func (interface {}) (datamodel.Node , error )
86
86
}
87
87
88
- type config map [reflect.Type ]* converter
88
+ type config struct {
89
+ namedConverters map [schema.TypeName ]* converter
90
+ typeConverters map [reflect.Type ]* converter
91
+ }
89
92
90
93
// this mainly exists to short-circuit the nonPtrType() call; the `Type()` variant
91
94
// exists for completeness
92
- func (c config ) converterFor (val reflect.Value ) * converter {
93
- if len ( c ) == 0 {
95
+ func (c * config ) converterFor (typeName schema. TypeName , val reflect.Value ) * converter {
96
+ if c == nil {
94
97
return nil
95
98
}
96
- return c [nonPtrType (val )]
99
+
100
+ if namedConverter , ok := c .namedConverters [typeName ]; ok {
101
+ return namedConverter
102
+ }
103
+
104
+ return c .typeConverters [nonPtrType (val )]
97
105
}
98
106
99
- func (c config ) converterForType (typ reflect.Type ) * converter {
100
- if len ( c ) == 0 {
107
+ func (c * config ) converterForType (typeName schema. TypeName , typ reflect.Type ) * converter {
108
+ if c == nil {
101
109
return nil
102
110
}
103
- return c [typ ]
111
+ if namedConverter , ok := c .namedConverters [typeName ]; ok {
112
+ return namedConverter
113
+ }
114
+
115
+ return c .typeConverters [typ ]
104
116
}
105
117
106
118
// Option is able to apply custom options to the bindnode API
107
- type Option func (config )
119
+ type Option func (* config )
108
120
109
121
// TypedBoolConverter adds custom converter functions for a particular
110
122
// type as identified by a pointer in the first argument.
@@ -121,8 +133,8 @@ func TypedBoolConverter(ptrVal interface{}, from func(bool) (interface{}, error)
121
133
customFromBool : from ,
122
134
customToBool : to ,
123
135
}
124
- return func (cfg config ) {
125
- cfg [customType ] = converter
136
+ return func (cfg * config ) {
137
+ cfg . typeConverters [customType ] = converter
126
138
}
127
139
}
128
140
@@ -141,8 +153,8 @@ func TypedIntConverter(ptrVal interface{}, from func(int64) (interface{}, error)
141
153
customFromInt : from ,
142
154
customToInt : to ,
143
155
}
144
- return func (cfg config ) {
145
- cfg [customType ] = converter
156
+ return func (cfg * config ) {
157
+ cfg . typeConverters [customType ] = converter
146
158
}
147
159
}
148
160
@@ -161,8 +173,8 @@ func TypedFloatConverter(ptrVal interface{}, from func(float64) (interface{}, er
161
173
customFromFloat : from ,
162
174
customToFloat : to ,
163
175
}
164
- return func (cfg config ) {
165
- cfg [customType ] = converter
176
+ return func (cfg * config ) {
177
+ cfg . typeConverters [customType ] = converter
166
178
}
167
179
}
168
180
@@ -181,8 +193,8 @@ func TypedStringConverter(ptrVal interface{}, from func(string) (interface{}, er
181
193
customFromString : from ,
182
194
customToString : to ,
183
195
}
184
- return func (cfg config ) {
185
- cfg [customType ] = converter
196
+ return func (cfg * config ) {
197
+ cfg . typeConverters [customType ] = converter
186
198
}
187
199
}
188
200
@@ -201,8 +213,8 @@ func TypedBytesConverter(ptrVal interface{}, from func([]byte) (interface{}, err
201
213
customFromBytes : from ,
202
214
customToBytes : to ,
203
215
}
204
- return func (cfg config ) {
205
- cfg [customType ] = converter
216
+ return func (cfg * config ) {
217
+ cfg . typeConverters [customType ] = converter
206
218
}
207
219
}
208
220
@@ -225,8 +237,8 @@ func TypedLinkConverter(ptrVal interface{}, from func(cid.Cid) (interface{}, err
225
237
customFromLink : from ,
226
238
customToLink : to ,
227
239
}
228
- return func (cfg config ) {
229
- cfg [customType ] = converter
240
+ return func (cfg * config ) {
241
+ cfg . typeConverters [customType ] = converter
230
242
}
231
243
}
232
244
@@ -248,18 +260,162 @@ func TypedAnyConverter(ptrVal interface{}, from func(datamodel.Node) (interface{
248
260
customFromAny : from ,
249
261
customToAny : to ,
250
262
}
251
- return func (cfg config ) {
252
- cfg [customType ] = converter
263
+ return func (cfg * config ) {
264
+ cfg .typeConverters [customType ] = converter
265
+ }
266
+ }
267
+
268
+ // NamedBoolConverter adds custom converter functions for given
269
+ // named schema type.
270
+ // The fromFunc is of the form: func(bool) (interface{}, error)
271
+ // and toFunc is of the form: func(interface{}) (bool, error)
272
+ // where interface{} is a pointer form of the type we are converting.
273
+ //
274
+ // NamedBoolConverter is an EXPERIMENTAL API and may be removed or
275
+ // changed in a future release.
276
+ func NamedBoolConverter (typeName schema.TypeName , from func (bool ) (interface {}, error ), to func (interface {}) (bool , error )) Option {
277
+ converter := & converter {
278
+ kind : schema .TypeKind_Bool ,
279
+ customFromBool : from ,
280
+ customToBool : to ,
281
+ }
282
+ return func (cfg * config ) {
283
+ cfg .namedConverters [typeName ] = converter
284
+ }
285
+ }
286
+
287
+ // NamedIntConverter adds custom converter functions for given
288
+ // named schema type.
289
+ // The fromFunc is of the form: func(int64) (interface{}, error)
290
+ // and toFunc is of the form: func(interface{}) (int64, error)
291
+ // where interface{} is a pointer form of the type we are converting.
292
+ //
293
+ // NamedIntConverter is an EXPERIMENTAL API and may be removed or
294
+ // changed in a future release.
295
+ func NamedIntConverter (typeName schema.TypeName , from func (int64 ) (interface {}, error ), to func (interface {}) (int64 , error )) Option {
296
+ converter := & converter {
297
+ kind : schema .TypeKind_Int ,
298
+ customFromInt : from ,
299
+ customToInt : to ,
300
+ }
301
+ return func (cfg * config ) {
302
+ cfg .namedConverters [typeName ] = converter
303
+ }
304
+ }
305
+
306
+ // NamedFloatConverter adds custom converter functions for given
307
+ // named schema type.
308
+ // The fromFunc is of the form: func(float64) (interface{}, error)
309
+ // and toFunc is of the form: func(interface{}) (float64, error)
310
+ // where interface{} is a pointer form of the type we are converting.
311
+ //
312
+ // NamedFloatConverter is an EXPERIMENTAL API and may be removed or
313
+ // changed in a future release.
314
+ func NamedFloatConverter (typeName schema.TypeName , from func (float64 ) (interface {}, error ), to func (interface {}) (float64 , error )) Option {
315
+ converter := & converter {
316
+ kind : schema .TypeKind_Float ,
317
+ customFromFloat : from ,
318
+ customToFloat : to ,
319
+ }
320
+ return func (cfg * config ) {
321
+ cfg .namedConverters [typeName ] = converter
322
+ }
323
+ }
324
+
325
+ // NamedStringConverter adds custom converter functions for given
326
+ // named schema type.
327
+ // The fromFunc is of the form: func(string) (interface{}, error)
328
+ // and toFunc is of the form: func(interface{}) (string, error)
329
+ // where interface{} is a pointer form of the type we are converting.
330
+ //
331
+ // NamedStringConverter is an EXPERIMENTAL API and may be removed or
332
+ // changed in a future release.
333
+ func NamedStringConverter (typeName schema.TypeName , from func (string ) (interface {}, error ), to func (interface {}) (string , error )) Option {
334
+ converter := & converter {
335
+ kind : schema .TypeKind_String ,
336
+ customFromString : from ,
337
+ customToString : to ,
338
+ }
339
+ return func (cfg * config ) {
340
+ cfg .namedConverters [typeName ] = converter
341
+ }
342
+ }
343
+
344
+ // NamedBytesConverter adds custom converter functions for given
345
+ // named schema type.
346
+ // The fromFunc is of the form: func([]byte) (interface{}, error)
347
+ // and toFunc is of the form: func(interface{}) ([]byte, error)
348
+ // where interface{} is a pointer form of the type we are converting.
349
+ //
350
+ // NamedBytesConverter is an EXPERIMENTAL API and may be removed or
351
+ // changed in a future release.
352
+ func NamedBytesConverter (typeName schema.TypeName , from func ([]byte ) (interface {}, error ), to func (interface {}) ([]byte , error )) Option {
353
+ converter := & converter {
354
+ kind : schema .TypeKind_Bytes ,
355
+ customFromBytes : from ,
356
+ customToBytes : to ,
357
+ }
358
+ return func (cfg * config ) {
359
+ cfg .namedConverters [typeName ] = converter
360
+ }
361
+ }
362
+
363
+ // NamedLinkConverter adds custom converter functions for given
364
+ // named schema type.
365
+ // The fromFunc is of the form: func([]byte) (interface{}, error)
366
+ // and toFunc is of the form: func(interface{}) ([]byte, error)
367
+ // where interface{} is a pointer form of the type we are converting.
368
+ //
369
+ // Beware that this API is only compatible with cidlink.Link types in the data
370
+ // model and may result in errors if attempting to convert from other
371
+ // datamodel.Link types.
372
+ //
373
+ // NamedLinkConverter is an EXPERIMENTAL API and may be removed or
374
+ // changed in a future release.
375
+ func NamedLinkConverter (typeName schema.TypeName , from func (cid.Cid ) (interface {}, error ), to func (interface {}) (cid.Cid , error )) Option {
376
+ converter := & converter {
377
+ kind : schema .TypeKind_Link ,
378
+ customFromLink : from ,
379
+ customToLink : to ,
380
+ }
381
+ return func (cfg * config ) {
382
+ cfg .namedConverters [typeName ] = converter
383
+ }
384
+ }
385
+
386
+ // NamedAnyConverter adds custom converter functions for given
387
+ // named schema type.
388
+ // The fromFunc is of the form: func(datamodel.Node) (interface{}, error)
389
+ // and toFunc is of the form: func(interface{}) (datamodel.Node, error)
390
+ // where interface{} is a pointer form of the type we are converting.
391
+ //
392
+ // This method should be able to deal with all forms of Any and return an error
393
+ // if the expected data forms don't match the expected.
394
+ //
395
+ // NamedAnyConverter is an EXPERIMENTAL API and may be removed or
396
+ // changed in a future release.
397
+ func NamedAnyConverter (typeName schema.TypeName , from func (datamodel.Node ) (interface {}, error ), to func (interface {}) (datamodel.Node , error )) Option {
398
+ converter := & converter {
399
+ kind : schema .TypeKind_Any ,
400
+ customFromAny : from ,
401
+ customToAny : to ,
402
+ }
403
+ return func (cfg * config ) {
404
+ cfg .namedConverters [typeName ] = converter
253
405
}
254
406
}
255
407
256
- func applyOptions (opt ... Option ) config {
408
+ func applyOptions (opt ... Option ) * config {
257
409
if len (opt ) == 0 {
258
410
// no need to allocate, we access it via converterFor and converterForType
259
411
// which are safe for nil maps
260
412
return nil
261
413
}
262
- cfg := make (map [reflect.Type ]* converter )
414
+ cfg := & config {
415
+ namedConverters : make (map [string ]* converter ),
416
+ typeConverters : make (map [reflect.Type ]* converter ),
417
+ }
418
+
263
419
for _ , o := range opt {
264
420
o (cfg )
265
421
}
0 commit comments