|
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