github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/cmd/info/internal/internal.go (about)

     1  package internal
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  )
     9  
    10  // Presence describes the presence of a filename in file listing
    11  type Presence int
    12  
    13  // Possible Presence states
    14  const (
    15  	Absent Presence = iota
    16  	Present
    17  	Renamed
    18  	Multiple
    19  )
    20  
    21  // Position is the placement of the test character in the filename
    22  type Position int
    23  
    24  // Predefined positions
    25  const (
    26  	PositionMiddle Position = 1 << iota
    27  	PositionLeft
    28  	PositionRight
    29  	PositionNone Position = 0
    30  	PositionAll  Position = PositionRight<<1 - 1
    31  )
    32  
    33  // PositionList contains all valid positions
    34  var PositionList = []Position{PositionMiddle, PositionLeft, PositionRight}
    35  
    36  // ControlResult contains the result of a single character test
    37  type ControlResult struct {
    38  	Text       string `json:"-"`
    39  	WriteError map[Position]string
    40  	GetError   map[Position]string
    41  	InList     map[Position]Presence
    42  }
    43  
    44  // InfoReport is the structure of the JSON output
    45  type InfoReport struct {
    46  	Remote               string
    47  	ControlCharacters    *map[string]ControlResult
    48  	MaxFileLength        *int
    49  	CanStream            *bool
    50  	CanWriteUnnormalized *bool
    51  	CanReadUnnormalized  *bool
    52  	CanReadRenormalized  *bool
    53  }
    54  
    55  func (e Position) String() string {
    56  	switch e {
    57  	case PositionNone:
    58  		return "none"
    59  	case PositionAll:
    60  		return "all"
    61  	}
    62  	var buf bytes.Buffer
    63  	if e&PositionMiddle != 0 {
    64  		buf.WriteString("middle")
    65  		e &= ^PositionMiddle
    66  	}
    67  	if e&PositionLeft != 0 {
    68  		if buf.Len() != 0 {
    69  			buf.WriteRune(',')
    70  		}
    71  		buf.WriteString("left")
    72  		e &= ^PositionLeft
    73  	}
    74  	if e&PositionRight != 0 {
    75  		if buf.Len() != 0 {
    76  			buf.WriteRune(',')
    77  		}
    78  		buf.WriteString("right")
    79  		e &= ^PositionRight
    80  	}
    81  	if e != PositionNone {
    82  		panic("invalid position")
    83  	}
    84  	return buf.String()
    85  }
    86  
    87  // MarshalText encodes the position when used as a map key
    88  func (e Position) MarshalText() ([]byte, error) {
    89  	return []byte(e.String()), nil
    90  }
    91  
    92  // UnmarshalText decodes a position when used as a map key
    93  func (e *Position) UnmarshalText(text []byte) error {
    94  	switch s := strings.ToLower(string(text)); s {
    95  	default:
    96  		*e = PositionNone
    97  		for _, p := range strings.Split(s, ",") {
    98  			switch p {
    99  			case "left":
   100  				*e |= PositionLeft
   101  			case "middle":
   102  				*e |= PositionMiddle
   103  			case "right":
   104  				*e |= PositionRight
   105  			default:
   106  				return fmt.Errorf("unknown position: %s", e)
   107  			}
   108  		}
   109  	case "none":
   110  		*e = PositionNone
   111  	case "all":
   112  		*e = PositionAll
   113  	}
   114  	return nil
   115  }
   116  
   117  func (e Presence) String() string {
   118  	switch e {
   119  	case Absent:
   120  		return "absent"
   121  	case Present:
   122  		return "present"
   123  	case Renamed:
   124  		return "renamed"
   125  	case Multiple:
   126  		return "multiple"
   127  	default:
   128  		panic("invalid presence")
   129  	}
   130  }
   131  
   132  // MarshalJSON encodes the presence when used as a JSON value
   133  func (e Presence) MarshalJSON() ([]byte, error) {
   134  	return json.Marshal(e.String())
   135  }
   136  
   137  // UnmarshalJSON decodes a presence when used as a JSON value
   138  func (e *Presence) UnmarshalJSON(text []byte) error {
   139  	var s string
   140  	if err := json.Unmarshal(text, &s); err != nil {
   141  		return err
   142  	}
   143  	switch s := strings.ToLower(s); s {
   144  	case "absent":
   145  		*e = Absent
   146  	case "present":
   147  		*e = Present
   148  	case "renamed":
   149  		*e = Renamed
   150  	case "multiple":
   151  		*e = Multiple
   152  	default:
   153  		return fmt.Errorf("unknown presence: %s", e)
   154  	}
   155  	return nil
   156  }