package types import ( "encoding" "fmt" "math/big" "strings" "github.com/filecoin-project/lotus/build" ) type FIL BigInt func (f FIL) String() string { r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(build.FilecoinPrecision))) if r.Sign() == 0 { return "0 FIL" } return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") + " FIL" } func (f FIL) Format(s fmt.State, ch rune) { switch ch { case 's', 'v': fmt.Fprint(s, f.String()) default: f.Int.Format(s, ch) } } func (f FIL) MarshalText() (text []byte, err error) { return []byte(f.String()), nil } func (f FIL) UnmarshalText(text []byte) error { p, err := ParseFIL(string(text)) if err != nil { return err } f.Int.Set(p.Int) return nil } func ParseFIL(s string) (FIL, error) { suffix := strings.TrimLeft(s, ".1234567890") s = s[:len(s)-len(suffix)] var attofil bool if suffix != "" { norm := strings.ToLower(strings.TrimSpace(suffix)) switch norm { case "", "fil": case "attofil", "afil": attofil = true default: return FIL{}, fmt.Errorf("unrecognized suffix: %q", suffix) } } r, ok := new(big.Rat).SetString(s) if !ok { return FIL{}, fmt.Errorf("failed to parse %q as a decimal number", s) } if !attofil { r = r.Mul(r, big.NewRat(int64(build.FilecoinPrecision), 1)) } if !r.IsInt() { var pref string if attofil { pref = "atto" } return FIL{}, fmt.Errorf("invalid %sFIL value: %q", pref, s) } return FIL{r.Num()}, nil } var _ encoding.TextMarshaler = (*FIL)(nil) var _ encoding.TextUnmarshaler = (*FIL)(nil)