|
15 | 15 | package cbor
|
16 | 16 |
|
17 | 17 | import (
|
| 18 | + "fmt" |
18 | 19 | "math/big"
|
19 | 20 | "reflect"
|
20 | 21 |
|
@@ -93,29 +94,57 @@ type Rat struct {
|
93 | 94 | }
|
94 | 95 |
|
95 | 96 | func (r *Rat) UnmarshalCBOR(cborData []byte) error {
|
96 |
| - tmpRat := []uint64{} |
| 97 | + tmpRat := []any{} |
97 | 98 | if _, err := Decode(cborData, &tmpRat); err != nil {
|
98 | 99 | return err
|
99 | 100 | }
|
100 |
| - // Convert numerator and denominator to big.Int |
101 |
| - // It's necessary to do this to support num/denom larger than int64 (up to uint64) |
| 101 | + // Convert numerator to big.Int |
102 | 102 | tmpNum := new(big.Int)
|
103 |
| - tmpNum.SetUint64(tmpRat[0]) |
| 103 | + switch v := tmpRat[0].(type) { |
| 104 | + case int64: |
| 105 | + tmpNum.SetInt64(v) |
| 106 | + case uint64: |
| 107 | + tmpNum.SetUint64(v) |
| 108 | + default: |
| 109 | + return fmt.Errorf("unsupported numerator type for cbor.Rat: %T", v) |
| 110 | + } |
| 111 | + // Convert denominator to big.Int |
104 | 112 | tmpDenom := new(big.Int)
|
105 |
| - tmpDenom.SetUint64(tmpRat[1]) |
| 113 | + switch v := tmpRat[1].(type) { |
| 114 | + case int64: |
| 115 | + tmpDenom.SetInt64(v) |
| 116 | + case uint64: |
| 117 | + tmpDenom.SetUint64(v) |
| 118 | + default: |
| 119 | + return fmt.Errorf("unsupported demoninator type for cbor.Rat: %T", v) |
| 120 | + } |
106 | 121 | // Create new big.Rat with num/denom set to big.Int values above
|
107 | 122 | r.Rat = new(big.Rat)
|
108 | 123 | r.Rat.SetFrac(tmpNum, tmpDenom)
|
109 | 124 | return nil
|
110 | 125 | }
|
111 | 126 |
|
112 | 127 | func (r *Rat) MarshalCBOR() ([]byte, error) {
|
| 128 | + tmpContent := make([]any, 2) |
| 129 | + // Numerator |
| 130 | + if r.Num().IsUint64() { |
| 131 | + tmpContent[0] = r.Num().Uint64() |
| 132 | + } else if r.Num().IsInt64() { |
| 133 | + tmpContent[0] = r.Num().Int64() |
| 134 | + } else { |
| 135 | + return nil, fmt.Errorf("numerator cannot be represented at int64/uint64") |
| 136 | + } |
| 137 | + // Denominator |
| 138 | + if r.Denom().IsUint64() { |
| 139 | + tmpContent[1] = r.Denom().Uint64() |
| 140 | + } else if r.Denom().IsInt64() { |
| 141 | + tmpContent[1] = r.Denom().Int64() |
| 142 | + } else { |
| 143 | + return nil, fmt.Errorf("numerator cannot be represented at int64/uint64") |
| 144 | + } |
113 | 145 | tmpData := _cbor.Tag{
|
114 |
| - Number: CborTagRational, |
115 |
| - Content: []uint64{ |
116 |
| - r.Num().Uint64(), |
117 |
| - r.Denom().Uint64(), |
118 |
| - }, |
| 146 | + Number: CborTagRational, |
| 147 | + Content: tmpContent, |
119 | 148 | }
|
120 | 149 | return Encode(&tmpData)
|
121 | 150 | }
|
|
0 commit comments