github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/tristate.go (about)

     1  package fs
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  // Tristate is a boolean that can has the states, true, false and
    11  // unset/invalid/nil
    12  type Tristate struct {
    13  	Value bool
    14  	Valid bool
    15  }
    16  
    17  // String renders the tristate as true/false/unset
    18  func (t Tristate) String() string {
    19  	if !t.Valid {
    20  		return "unset"
    21  	}
    22  	if t.Value {
    23  		return "true"
    24  	}
    25  	return "false"
    26  }
    27  
    28  // Set the List entries
    29  func (t *Tristate) Set(s string) error {
    30  	s = strings.ToLower(s)
    31  	if s == "" || s == "nil" || s == "null" || s == "unset" {
    32  		t.Valid = false
    33  		return nil
    34  	}
    35  	value, err := strconv.ParseBool(s)
    36  	if err != nil {
    37  		return fmt.Errorf("failed to parse Tristate %q: %w", s, err)
    38  	}
    39  	t.Value = value
    40  	t.Valid = true
    41  	return nil
    42  }
    43  
    44  // Type of the value
    45  func (Tristate) Type() string {
    46  	return "Tristate"
    47  }
    48  
    49  // Scan implements the fmt.Scanner interface
    50  func (t *Tristate) Scan(s fmt.ScanState, ch rune) error {
    51  	token, err := s.Token(true, nil)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	return t.Set(string(token))
    56  }
    57  
    58  // UnmarshalJSON parses it as a bool or nil for unset
    59  func (t *Tristate) UnmarshalJSON(in []byte) error {
    60  	var b *bool
    61  	err := json.Unmarshal(in, &b)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	if b != nil {
    66  		t.Valid = true
    67  		t.Value = *b
    68  	} else {
    69  		t.Valid = false
    70  	}
    71  	return nil
    72  }
    73  
    74  // MarshalJSON encodes it as a bool or nil for unset
    75  func (t *Tristate) MarshalJSON() ([]byte, error) {
    76  	if !t.Valid {
    77  		return json.Marshal(nil)
    78  	}
    79  	return json.Marshal(t.Value)
    80  }