@@ -282,6 +282,98 @@ func TestDecimalFixedSpecCompliantTextualRoundTrip(t *testing.T) {
282282 }
283283}
284284
285+ func TestDecimalBytesLegacyTextualRoundTrip (t * testing.T ) {
286+ // Test legacy (default) textual encoding with escaped bytes format
287+ schema := `{"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 2}`
288+
289+ // Create codec with default options (legacy encoding)
290+ codec , err := NewCodec (schema )
291+ if err != nil {
292+ t .Fatal (err )
293+ }
294+
295+ testCases := []struct {
296+ native * big.Rat
297+ expected string // escaped bytes format
298+ }{
299+ {big .NewRat (4020 , 100 ), `"\u000F\u00B4"` }, // 4020 = 0x0FB4
300+ {big .NewRat (1234 , 100 ), `"\u0004\u00D2"` }, // 1234 = 0x04D2
301+ {big .NewRat (- 1234 , 100 ), `"\u00FB."` }, // -1234 in two's complement
302+ {big .NewRat (0 , 1 ), `"\u0000"` }, // 0
303+ {big .NewRat (9999 , 100 ), `"'\u000F"` }, // 9999 = 0x270F
304+ }
305+
306+ for _ , tc := range testCases {
307+ // Encode native to textual
308+ textual , err := codec .TextualFromNative (nil , tc .native )
309+ if err != nil {
310+ t .Fatalf ("TextualFromNative(%v): %v" , tc .native , err )
311+ }
312+
313+ if string (textual ) != tc .expected {
314+ t .Errorf ("TextualFromNative(%v): got %s, want %s" , tc .native , textual , tc .expected )
315+ }
316+
317+ // Decode textual back to native
318+ native , _ , err := codec .NativeFromTextual (textual )
319+ if err != nil {
320+ t .Fatalf ("NativeFromTextual(%s): %v" , textual , err )
321+ }
322+
323+ rat , ok := native .(* big.Rat )
324+ if ! ok {
325+ t .Fatalf ("NativeFromTextual(%s): expected *big.Rat, got %T" , textual , native )
326+ }
327+
328+ if rat .Cmp (tc .native ) != 0 {
329+ t .Errorf ("NativeFromTextual(%s): got %v, want %v" , textual , rat , tc .native )
330+ }
331+ }
332+ }
333+
334+ func TestDecimalFixedLegacyTextualRoundTrip (t * testing.T ) {
335+ // Test legacy (default) textual encoding with escaped bytes format for fixed type
336+ schema := `{"type": "fixed", "size": 12, "logicalType": "decimal", "precision": 4, "scale": 2}`
337+
338+ // Create codec with default options (legacy encoding)
339+ codec , err := NewCodec (schema )
340+ if err != nil {
341+ t .Fatal (err )
342+ }
343+
344+ testCases := []struct {
345+ native * big.Rat
346+ }{
347+ {big .NewRat (4020 , 100 )},
348+ {big .NewRat (1234 , 100 )},
349+ {big .NewRat (- 1234 , 100 )},
350+ // Note: 0 is not tested here due to fixed size constraints
351+ }
352+
353+ for _ , tc := range testCases {
354+ // Encode native to textual
355+ textual , err := codec .TextualFromNative (nil , tc .native )
356+ if err != nil {
357+ t .Fatalf ("TextualFromNative(%v): %v" , tc .native , err )
358+ }
359+
360+ // Decode textual back to native - should round-trip correctly
361+ native , _ , err := codec .NativeFromTextual (textual )
362+ if err != nil {
363+ t .Fatalf ("NativeFromTextual(%s): %v" , textual , err )
364+ }
365+
366+ rat , ok := native .(* big.Rat )
367+ if ! ok {
368+ t .Fatalf ("NativeFromTextual(%s): expected *big.Rat, got %T" , textual , native )
369+ }
370+
371+ if rat .Cmp (tc .native ) != 0 {
372+ t .Errorf ("Round-trip failed for %v: got %v" , tc .native , rat )
373+ }
374+ }
375+ }
376+
285377func TestDecimalBytesCorrectBinaryEncoding (t * testing.T ) {
286378 // Test that binary encoding uses two's complement (same for both legacy and spec-compliant)
287379 schema := `{"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 2}`
0 commit comments